mirror of
https://github.com/fastapi-users/fastapi-users.git
synced 2026-03-13 07:49:55 +08:00
Rework the documentation
This commit is contained in:
@@ -9,11 +9,7 @@ from fastapi_users.authentication import CookieAuthentication
|
||||
|
||||
SECRET = "SECRET"
|
||||
|
||||
auth_backends = []
|
||||
|
||||
cookie_authentication = CookieAuthentication(secret=SECRET, lifetime_seconds=3600)
|
||||
|
||||
auth_backends.append(cookie_authentication)
|
||||
```
|
||||
|
||||
As you can see, instantiation is quite simple. It accepts the following arguments:
|
||||
@@ -58,7 +54,3 @@ This method will remove the authentication cookie:
|
||||
## Authentication
|
||||
|
||||
This method expects that you provide a valid cookie in the headers.
|
||||
|
||||
## Next steps
|
||||
|
||||
We will now configure the main **FastAPI Users** object that will expose the [routers](../routers/index.md).
|
||||
|
||||
@@ -9,11 +9,7 @@ from fastapi_users.authentication import JWTAuthentication
|
||||
|
||||
SECRET = "SECRET"
|
||||
|
||||
auth_backends = []
|
||||
|
||||
jwt_authentication = JWTAuthentication(secret=SECRET, lifetime_seconds=3600, tokenUrl="auth/jwt/login")
|
||||
|
||||
auth_backends.append(jwt_authentication)
|
||||
```
|
||||
|
||||
As you can see, instantiation is quite simple. It accepts the following arguments:
|
||||
@@ -69,7 +65,3 @@ from fastapi import Depends, Response
|
||||
async def refresh_jwt(response: Response, user=Depends(fastapi_users.current_user(active=True))):
|
||||
return await jwt_authentication.get_login_response(user, response)
|
||||
```
|
||||
|
||||
## Next steps
|
||||
|
||||
We will now configure the main **FastAPI Users** object that will expose the [routers](../routers/index.md).
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
Let's create a MongoDB connection and instantiate a collection.
|
||||
|
||||
```py hl_lines="23 24 25 26"
|
||||
```py hl_lines="6 7 8 9 10 11"
|
||||
{!./src/db_mongodb.py!}
|
||||
```
|
||||
|
||||
@@ -17,20 +17,16 @@ You can choose any name for the database and the collection.
|
||||
|
||||
## Create the database adapter
|
||||
|
||||
The database adapter of **FastAPI Users** makes the link between your database configuration and the users logic. Create it like this.
|
||||
The database adapter of **FastAPI Users** makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency.
|
||||
|
||||
```py hl_lines="34"
|
||||
```py hl_lines="14 15"
|
||||
{!./src/db_mongodb.py!}
|
||||
```
|
||||
|
||||
Notice that we pass a reference to your [`UserDB` model](../model.md).
|
||||
Notice that we pass a reference to your [`UserDB` model](../models.md).
|
||||
|
||||
!!! info
|
||||
The database adapter will automatically create a [unique index](https://docs.mongodb.com/manual/core/index-unique/) on `id` and `email`.
|
||||
|
||||
!!! warning
|
||||
**FastAPI Users** will use its defined [`id` UUID](../model.md) as unique identifier for the user, rather than the builtin MongoDB `_id`.
|
||||
|
||||
## Next steps
|
||||
|
||||
We will now configure an [authentication method](../authentication/index.md).
|
||||
**FastAPI Users** will use its defined [`id` UUID](../models.md) as unique identifier for the user, rather than the builtin MongoDB `_id`.
|
||||
|
||||
@@ -24,7 +24,7 @@ For the sake of this tutorial from now on, we'll use a simple SQLite databse.
|
||||
|
||||
Let's declare our User ORM model.
|
||||
|
||||
```py hl_lines="29-33"
|
||||
```py hl_lines="11-15"
|
||||
{!./src/db_ormar.py!}
|
||||
```
|
||||
|
||||
@@ -35,19 +35,15 @@ there to fit to your needs!
|
||||
## Create the database adapter
|
||||
|
||||
The database adapter of **FastAPI Users** makes the link between your
|
||||
database configuration and the users logic. Create it like this.
|
||||
database configuration and the users logic. It should be generated by a FastAPI dependency.
|
||||
|
||||
```py hl_lines="40"
|
||||
```py hl_lines="22-23"
|
||||
{!./src/db_ormar.py!}
|
||||
```
|
||||
|
||||
Notice that we pass a reference to your [`UserDB` model](../model.md).
|
||||
Notice that we pass a reference to your [`UserDB` model](../models.md).
|
||||
|
||||
!!! warning
|
||||
In production, it's strongly recommended to setup a migration system to
|
||||
update your SQL schemas. See
|
||||
[Alembic](https://alembic.sqlalchemy.org/en/latest/).
|
||||
|
||||
## Next steps
|
||||
|
||||
We will now configure an [authentication method](../authentication/index.md).
|
||||
|
||||
@@ -22,42 +22,38 @@ For the sake of this tutorial from now on, we'll use a simple SQLite databse.
|
||||
|
||||
## Setup User table
|
||||
|
||||
Let's create a `metadata` object and declare our User table.
|
||||
Let's declare our SQLAlchemy `User` table.
|
||||
|
||||
```py hl_lines="5 32 33"
|
||||
```py hl_lines="13 14"
|
||||
{!./src/db_sqlalchemy.py!}
|
||||
```
|
||||
|
||||
As you can see, **FastAPI Users** provides a mixin that will include base fields for our User table. You can of course add you own fields there to fit to your needs!
|
||||
As you can see, **FastAPI Users** provides a mixin that will include base fields for our `User` table. You can of course add you own fields there to fit to your needs!
|
||||
|
||||
## Create the tables
|
||||
|
||||
We'll now create an SQLAlchemy engine and ask it to create all the defined tables.
|
||||
|
||||
```py hl_lines="36 37 38 39 40"
|
||||
```py hl_lines="17 18 19 20"
|
||||
{!./src/db_sqlalchemy.py!}
|
||||
```
|
||||
|
||||
!!! warning
|
||||
In production, it's strongly recommended to setup a migration system to update your SQL schemas. See [Alembic](https://alembic.sqlalchemy.org/en/latest/).
|
||||
|
||||
## Create the database adapter
|
||||
## Create the database adapter dependency
|
||||
|
||||
The database adapter of **FastAPI Users** makes the link between your database configuration and the users logic. Create it like this.
|
||||
The database adapter of **FastAPI Users** makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency.
|
||||
|
||||
```py hl_lines="42 43"
|
||||
```py hl_lines="25 26"
|
||||
{!./src/db_sqlalchemy.py!}
|
||||
```
|
||||
|
||||
Notice that we pass it three things:
|
||||
|
||||
* A reference to your [`UserDB` model](../model.md).
|
||||
* The `users` variable, which is the actual SQLAlchemy table behind the table class.
|
||||
* A reference to your [`UserDB` model](../models.md).
|
||||
* A `database` instance, which allows us to do asynchronous request to the database.
|
||||
|
||||
## Next steps
|
||||
|
||||
We will now configure an [authentication method](../authentication/index.md).
|
||||
* The `users` variable, which is the actual SQLAlchemy table behind the table class.
|
||||
|
||||
## What about SQLAlchemy ORM?
|
||||
|
||||
|
||||
@@ -20,35 +20,33 @@ pip install aiosqlite
|
||||
|
||||
For the sake of this tutorial from now on, we'll use a simple SQLite databse.
|
||||
|
||||
## Setup User table
|
||||
## Setup User table and model
|
||||
|
||||
Let's declare our User ORM model.
|
||||
|
||||
```py hl_lines="8 9"
|
||||
{!./src/db_tortoise.py!}
|
||||
```py hl_lines="18 19"
|
||||
{!./src/db_tortoise_model.py!}
|
||||
```
|
||||
|
||||
As you can see, **FastAPI Users** provides an abstract model that will include base fields for our User table. You can of course add you own fields there to fit to your needs!
|
||||
|
||||
## Tweak `UserDB` model
|
||||
|
||||
In order to make the Pydantic model and the Tortoise ORM model working well together, you'll have to add a mixin and some configuration options to your `UserDB` model. Tortoise ORM provides [utilities to ease the integration with Pydantic](https://tortoise-orm.readthedocs.io/en/latest/contrib/pydantic.html) and we'll use them here.
|
||||
|
||||
```py hl_lines="5 24 25 26 27"
|
||||
{!./src/db_tortoise.py!}
|
||||
```py hl_lines="22 23 24 25 26"
|
||||
{!./src/db_tortoise_model.py!}
|
||||
```
|
||||
|
||||
The `PydanticModel` mixin adds methods used internally by Tortoise ORM to the Pydantic model so that it can easily transform it back to an ORM model. It expects then that you provide the property `orig_model` which should point to the **User ORM model we defined just above**.
|
||||
|
||||
## Create the database adapter
|
||||
|
||||
The database adapter of **FastAPI Users** makes the link between your database configuration and the users logic. Create it like this.
|
||||
The database adapter of **FastAPI Users** makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency.
|
||||
|
||||
```py hl_lines="32"
|
||||
{!./src/db_tortoise.py!}
|
||||
```py hl_lines="8 9"
|
||||
{!./src/db_tortoise_adapter.py!}
|
||||
```
|
||||
|
||||
Notice that we pass a reference to your [`UserDB` model](../model.md).
|
||||
Notice that we pass a reference to your [`UserDB` model](../models.md).
|
||||
|
||||
## Register Tortoise
|
||||
|
||||
@@ -56,13 +54,16 @@ For using Tortoise ORM we must register our models and database.
|
||||
|
||||
Tortoise ORM supports integration with FastAPI out-of-the-box. It will automatically bind startup and shutdown events.
|
||||
|
||||
```py hl_lines="35 36 37 38 39 40"
|
||||
{!./src/db_tortoise.py!}
|
||||
```py
|
||||
from tortoise.contrib.fastapi import register_tortoise
|
||||
|
||||
register_tortoise(
|
||||
app,
|
||||
db_url=DATABASE_URL,
|
||||
modules={"models": ["models"]},
|
||||
generate_schemas=True,
|
||||
)
|
||||
```
|
||||
|
||||
!!! warning
|
||||
In production, it's strongly recommended to setup a migration system to update your SQL schemas. See [https://tortoise-orm.readthedocs.io/en/latest/migration.html](https://tortoise-orm.readthedocs.io/en/latest/migration.html).
|
||||
|
||||
## Next steps
|
||||
|
||||
We will now configure an [authentication method](../authentication/index.md).
|
||||
|
||||
@@ -8,27 +8,20 @@ Here is a full working example with JWT authentication to help get you started.
|
||||
|
||||
## SQLAlchemy
|
||||
|
||||
```py
|
||||
{!./src/full_sqlalchemy.py!}
|
||||
```
|
||||
<iframe frameborder="0" width="100%" height="500px" src="https://replit.com/@frankie567/fastapi-users-sqlalchemy?embed=true"></iframe>
|
||||
|
||||
|
||||
## MongoDB
|
||||
|
||||
```py
|
||||
{!./src/full_mongodb.py!}
|
||||
```
|
||||
<iframe frameborder="0" width="100%" height="500px" src="https://replit.com/@frankie567/fastapi-users-mongodb?embed=true"></iframe>
|
||||
|
||||
## Tortoise ORM
|
||||
|
||||
```py
|
||||
{!./src/full_tortoise.py!}
|
||||
```
|
||||
<iframe frameborder="0" width="100%" height="500px" src="https://replit.com/@frankie567/fastapi-users-tortoise?embed=true"></iframe>
|
||||
|
||||
## Ormar
|
||||
|
||||
```py
|
||||
{!./src/full_ormar.py!}
|
||||
```
|
||||
<iframe frameborder="0" width="100%" height="500px" src="https://replit.com/@frankie567/fastapi-users-ormar?embed=true"></iframe>
|
||||
|
||||
## What now?
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# User model
|
||||
# Models
|
||||
|
||||
**FastAPI Users** defines a minimal User model for authentication purposes. It is structured like this:
|
||||
|
||||
@@ -67,15 +67,3 @@ class UserUpdate(models.BaseUserUpdate):
|
||||
class UserDB(User, models.BaseUserDB):
|
||||
pass
|
||||
```
|
||||
|
||||
## Next steps
|
||||
|
||||
Depending on your database backend, the database configuration will differ a bit.
|
||||
|
||||
[I'm using SQLAlchemy](databases/sqlalchemy.md)
|
||||
|
||||
[I'm using MongoDB](databases/mongodb.md)
|
||||
|
||||
[I'm using Tortoise ORM](databases/tortoise.md)
|
||||
|
||||
[I'm using ormar](databases/ormar.md)
|
||||
@@ -46,7 +46,7 @@ class UserCreate(models.BaseUserCreate):
|
||||
pass
|
||||
|
||||
|
||||
class UserUpdate(User, models.BaseUserUpdate):
|
||||
class UserUpdate(models.BaseUserUpdate):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
92
docs/configuration/overview.md
Normal file
92
docs/configuration/overview.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# Overview
|
||||
|
||||
The schema below shows you how the library is structured and how each part fit together.
|
||||
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
FASTAPI_USERS{FastAPIUsers}
|
||||
USER_MANAGER{UserManager}
|
||||
USER_MANAGER_DEPENDENCY[[get_user_manager]]
|
||||
CURRENT_USER[[current_user]]
|
||||
subgraph MODELS[Models]
|
||||
direction RL
|
||||
USER[User]
|
||||
USER_CREATE[UserCreate]
|
||||
USER_UPDATE[UserUpdate]
|
||||
USER_DB[UserDB]
|
||||
end
|
||||
subgraph DATABASE[Database adapters]
|
||||
direction RL
|
||||
SQLALCHEMY[SQLAlchemy]
|
||||
MONGODB[MongoDB]
|
||||
TORTOISE[Tortoise ORM]
|
||||
ORMAR[Ormar]
|
||||
end
|
||||
subgraph ROUTERS[Routers]
|
||||
direction RL
|
||||
REGISTER[[get_register_router]]
|
||||
VERIFY[[get_verify_router]]
|
||||
RESET[[get_reset_password_router]]
|
||||
AUTH[[get_auth_router]]
|
||||
OAUTH[[get_oauth_router]]
|
||||
USERS[[get_users_router]]
|
||||
end
|
||||
subgraph AUTH_BACKENDS[Authentication backends]
|
||||
direction RL
|
||||
COOKIE[CookieAuthentication]
|
||||
JWT[JWTAuthentication]
|
||||
end
|
||||
DATABASE --> USER_MANAGER
|
||||
|
||||
MODELS --> USER_MANAGER
|
||||
MODELS --> FASTAPI_USERS
|
||||
|
||||
USER_MANAGER --> USER_MANAGER_DEPENDENCY
|
||||
USER_MANAGER_DEPENDENCY --> FASTAPI_USERS
|
||||
|
||||
FASTAPI_USERS --> ROUTERS
|
||||
|
||||
AUTH_BACKENDS --> AUTH
|
||||
AUTH_BACKENDS --> FASTAPI_USERS
|
||||
|
||||
FASTAPI_USERS --> CURRENT_USER
|
||||
```
|
||||
|
||||
## Models
|
||||
|
||||
Pydantic models representing the data structure of a user. Base classes are provided with the required fields to make authentication work. You should sub-class each of them and add your own fields there.
|
||||
|
||||
➡️ [Configure the models](./models.md)
|
||||
|
||||
## Database adapters
|
||||
|
||||
FastAPI Users is compatible with various databases and ORM. To build the interface between those database tools and the library, we provide database adapters classes that you need to instantiate and configure.
|
||||
|
||||
➡️ [I'm using SQLAlchemy](databases/sqlalchemy.md)
|
||||
|
||||
➡️ [I'm using MongoDB](databases/mongodb.md)
|
||||
|
||||
➡️ [I'm using Tortoise ORM](databases/tortoise.md)
|
||||
|
||||
➡️ [I'm using ormar](databases/ormar.md)
|
||||
|
||||
## Authentication backends
|
||||
|
||||
Authentication backends define the way users sessions are managed in your app, like access tokens or cookies.
|
||||
|
||||
➡️ [Configure the authentication backends](./authentication/index.md)
|
||||
|
||||
## `UserManager`
|
||||
|
||||
The `UserManager` object bears most of the logic of FastAPI Users: registration, verification, password reset... We provide a `BaseUserManager` with this common logic; which you should overload to define how to validate passwords or handle events.
|
||||
|
||||
This `UserManager` object should be provided through a FastAPI dependency, `get_user_manager`.
|
||||
|
||||
➡️ [Configure `UserManager`](./user-manager.md)
|
||||
|
||||
## `FastAPIUsers` and routers
|
||||
|
||||
Finally, `FastAPIUsers` object is the main class from which you'll be able to generate routers for classic routes like registration or login, but also get the `current_user` dependency factory to inject the authenticated user in your own routes.
|
||||
|
||||
➡️ [Configure `FastAPIUsers` and routers](./routers/index.md)
|
||||
@@ -1,49 +0,0 @@
|
||||
# Password validation
|
||||
|
||||
FastAPI Users **doesn't have any password validation logic by default**. However, there is an argument on the `FastAPIUsers` class so that you can provide your own password validation function.
|
||||
|
||||
It'll be applied on each routes that need to validate the input password:
|
||||
|
||||
* At registration ([`/register`](../usage/routes.md#post-register))
|
||||
* At password reset ([`/reset-password`](../usage/routes.md#post-reset-password))
|
||||
* At profile update ([`/me`](../usage/routes.md#patch-me) and [`/{user_id}`](../usage/routes.md#patch-user_id))
|
||||
|
||||
## Configuration
|
||||
|
||||
The FastAPIUsers class accepts an optional keyword argument `validate_password`. It expects an async function which accepts in argument:
|
||||
|
||||
* `password` (`str`): the password to validate.
|
||||
* `user` (`Union[UserRegister, User]`): user model which we are currently validating the password. Useful if you want to check that the password doesn't contain the name or the birthdate of the user for example.
|
||||
|
||||
This function should return `None` if the password is valid or raise `InvalidPasswordException` if not. This exception expects an argument `reason` telling why the password is invalid. It'll be part of the error response.
|
||||
|
||||
## Example
|
||||
|
||||
```py
|
||||
from fastapi_users import FastAPIUsers, InvalidPasswordException
|
||||
|
||||
|
||||
async def validate_password(
|
||||
password: str,
|
||||
user: Union[UserCreate, User],
|
||||
) -> None:
|
||||
if len(password) < 8:
|
||||
raise InvalidPasswordException(
|
||||
reason="Password should be at least 8 characters"
|
||||
)
|
||||
if user.email in password:
|
||||
raise InvalidPasswordException(
|
||||
reason="Password should not contain e-mail"
|
||||
)
|
||||
|
||||
|
||||
fastapi_users = FastAPIUsers(
|
||||
user_db,
|
||||
[jwt_authentication],
|
||||
User,
|
||||
UserCreate,
|
||||
UserUpdate,
|
||||
UserDB,
|
||||
validate_password=validate_password
|
||||
)
|
||||
```
|
||||
@@ -16,7 +16,7 @@ SECRET = "SECRET"
|
||||
jwt_authentication = JWTAuthentication(secret=SECRET, lifetime_seconds=3600)
|
||||
|
||||
fastapi_users = FastAPIUsers(
|
||||
user_db,
|
||||
get_user_manager,
|
||||
[jwt_authentication],
|
||||
User,
|
||||
UserCreate,
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
# Routers
|
||||
|
||||
We're almost there! The last step is to configure the `FastAPIUsers` object that will wire the database adapter, the authentication classes and let us generate the actual **API routes**.
|
||||
We're almost there! The last step is to configure the `FastAPIUsers` object that will wire the user manager, the authentication classes and let us generate the actual **API routes**.
|
||||
|
||||
## Configure `FastAPIUsers`
|
||||
|
||||
Configure `FastAPIUsers` object with all the elements we defined before. More precisely:
|
||||
|
||||
* `db`: Database adapter instance.
|
||||
* `get_user_manager`: Dependency callable getter to inject the
|
||||
user manager class instance. See [UserManager](../user-manager.md).
|
||||
* `auth_backends`: List of authentication backends. See [Authentication](../authentication/index.md).
|
||||
* `user_model`: Pydantic model of a user.
|
||||
* `user_create_model`: Pydantic model for creating a user.
|
||||
@@ -17,8 +18,8 @@ Configure `FastAPIUsers` object with all the elements we defined before. More pr
|
||||
from fastapi_users import FastAPIUsers
|
||||
|
||||
fastapi_users = FastAPIUsers(
|
||||
user_db,
|
||||
auth_backends,
|
||||
get_user_manager,
|
||||
[jwt_authentication],
|
||||
User,
|
||||
UserCreate,
|
||||
UserUpdate,
|
||||
|
||||
@@ -16,7 +16,7 @@ SECRET = "SECRET"
|
||||
jwt_authentication = JWTAuthentication(secret=SECRET, lifetime_seconds=3600)
|
||||
|
||||
fastapi_users = FastAPIUsers(
|
||||
user_db,
|
||||
get_user_manager,
|
||||
[jwt_authentication],
|
||||
User,
|
||||
UserCreate,
|
||||
@@ -31,24 +31,3 @@ app.include_router(
|
||||
tags=["auth"],
|
||||
)
|
||||
```
|
||||
|
||||
## After register
|
||||
|
||||
You can provide a custom function to be called after a successful registration. It is called with **two arguments**: the **user** that has just registered, and the original **`Request` object**.
|
||||
|
||||
Typically, you'll want to **send a welcome e-mail** or add it to your marketing analytics pipeline.
|
||||
|
||||
You can define it as an `async` or standard method.
|
||||
|
||||
Example:
|
||||
|
||||
```py
|
||||
def on_after_register(user: UserDB, request: Request):
|
||||
print(f"User {user.id} has registered.")
|
||||
|
||||
app.include_router(
|
||||
fastapi_users.get_register_router(on_after_register),
|
||||
prefix="/auth",
|
||||
tags=["auth"],
|
||||
)
|
||||
```
|
||||
|
||||
@@ -10,9 +10,13 @@ Check the [routes usage](../../usage/routes.md) to learn how to use them.
|
||||
from fastapi import FastAPI
|
||||
from fastapi_users import FastAPIUsers
|
||||
|
||||
SECRET = "SECRET"
|
||||
|
||||
jwt_authentication = JWTAuthentication(secret=SECRET, lifetime_seconds=3600)
|
||||
|
||||
fastapi_users = FastAPIUsers(
|
||||
user_db,
|
||||
auth_backends,
|
||||
get_user_manager,
|
||||
[jwt_authentication],
|
||||
User,
|
||||
UserCreate,
|
||||
UserUpdate,
|
||||
@@ -21,62 +25,7 @@ fastapi_users = FastAPIUsers(
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(
|
||||
fastapi_users.get_reset_password_router("SECRET"),
|
||||
prefix="/auth",
|
||||
tags=["auth"],
|
||||
)
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
* `reset_password_token_secret` (`Union[str, pydantic.SecretStr]`): Secret to encode reset password token.
|
||||
* `reset_password_token_lifetime_seconds` (`int`): Lifetime of reset password token. **Defaults to 3600**.
|
||||
* `after_forgot_password`: Optional function called after a successful forgot password request. See below.
|
||||
|
||||
## After forgot password
|
||||
|
||||
You can provide a custom function to be called after a successful forgot password request. It is called with **three arguments**:
|
||||
|
||||
* The **user** which has requested to reset their password.
|
||||
* A ready-to-use **JWT token** that will be accepted by the reset password route.
|
||||
* The original **`Request` object**.
|
||||
|
||||
Typically, you'll want to **send an e-mail** with the link (and the token) that allows the user to reset their password.
|
||||
|
||||
You can define it as an `async` or standard method.
|
||||
|
||||
Example:
|
||||
|
||||
```py
|
||||
def on_after_forgot_password(user: UserDB, token: str, request: Request):
|
||||
print(f"User {user.id} has forgot their password. Reset token: {token}")
|
||||
|
||||
app.include_router(
|
||||
fastapi_users.get_reset_password_router("SECRET", after_forgot_password=on_after_forgot_password),
|
||||
prefix="/auth",
|
||||
tags=["auth"],
|
||||
)
|
||||
```
|
||||
|
||||
## After reset password
|
||||
|
||||
You can provide a custom function to be called after a successful password reset. It is called with **two arguments**:
|
||||
|
||||
* The **user** which has reset their password.
|
||||
* The original **`Request` object**.
|
||||
|
||||
For example, you may want to **send an e-mail** to the concerned user to warn him that their password has been changed and that they should take action if they think they have been hacked.
|
||||
|
||||
You can define it as an `async` or standard method.
|
||||
|
||||
Example:
|
||||
|
||||
```py
|
||||
def on_after_reset_password(user: UserDB, request: Request):
|
||||
print(f"User {user.id} has reset their password.")
|
||||
|
||||
app.include_router(
|
||||
fastapi_users.get_reset_password_router("SECRET", after_reset_password=on_after_reset_password),
|
||||
fastapi_users.get_reset_password_router(),
|
||||
prefix="/auth",
|
||||
tags=["auth"],
|
||||
)
|
||||
|
||||
@@ -8,9 +8,13 @@ This router provides routes to manage users. Check the [routes usage](../../usag
|
||||
from fastapi import FastAPI
|
||||
from fastapi_users import FastAPIUsers
|
||||
|
||||
SECRET = "SECRET"
|
||||
|
||||
jwt_authentication = JWTAuthentication(secret=SECRET, lifetime_seconds=3600)
|
||||
|
||||
fastapi_users = FastAPIUsers(
|
||||
user_db,
|
||||
auth_backends,
|
||||
get_user_manager,
|
||||
[jwt_authentication],
|
||||
User,
|
||||
UserCreate,
|
||||
UserUpdate,
|
||||
@@ -36,28 +40,3 @@ app.include_router(
|
||||
tags=["users"],
|
||||
)
|
||||
```
|
||||
|
||||
## After update
|
||||
|
||||
You can provide a custom function to be called after a successful update user request. It is called with **three arguments**:
|
||||
|
||||
* The **user** which was updated.
|
||||
* The dictionary containing the updated fields.
|
||||
* The original **`Request` object**.
|
||||
|
||||
It may be useful, for example, if you wish to update your user in a data analytics or customer success platform.
|
||||
|
||||
You can define it as an `async` or standard method.
|
||||
|
||||
Example:
|
||||
|
||||
```py
|
||||
def on_after_update(user: UserDB, updated_user_data: Dict[str, Any], request: Request):
|
||||
print(f"User {user.id} has been updated with the following data: {updated_user_data}")
|
||||
|
||||
app.include_router(
|
||||
fastapi_users.get_users_router(on_after_update),
|
||||
prefix="/users",
|
||||
tags=["users"],
|
||||
)
|
||||
```
|
||||
|
||||
@@ -11,9 +11,13 @@ This router provides routes to manage user email verification. Check the [routes
|
||||
from fastapi import FastAPI
|
||||
from fastapi_users import FastAPIUsers
|
||||
|
||||
SECRET = "SECRET"
|
||||
|
||||
jwt_authentication = JWTAuthentication(secret=SECRET, lifetime_seconds=3600)
|
||||
|
||||
fastapi_users = FastAPIUsers(
|
||||
user_db,
|
||||
auth_backends,
|
||||
get_user_manager,
|
||||
[jwt_authentication],
|
||||
User,
|
||||
UserCreate,
|
||||
UserUpdate,
|
||||
@@ -22,63 +26,7 @@ fastapi_users = FastAPIUsers(
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(
|
||||
fastapi_users.get_verify_router("SECRET"),
|
||||
prefix="/auth",
|
||||
tags=["auth"],
|
||||
)
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
* `verification_token_secret` (`Union[str, pydantic.SecretStr]`): Secret to encode verify token.
|
||||
* `verification_token_lifetime_seconds` (`int`): Lifetime of verify token. **Defaults to 3600**.
|
||||
* `after_verification_request`: Optional function called after a successful verify request. See below.
|
||||
* `after_verification`: Optional function called after a successful verification. See below.
|
||||
|
||||
## After verification request
|
||||
|
||||
You can provide a custom function to be called after a successful verification request. It is called with **three arguments**:
|
||||
|
||||
* The **user** for which the verification has been requested.
|
||||
* A ready-to-use **JWT token** that will be accepted by the verify route.
|
||||
* The original **`Request` object**.
|
||||
|
||||
Typically, you'll want to **send an e-mail** with the link (and the token) that allows the user to verify their e-mail.
|
||||
|
||||
You can define it as an `async` or standard method.
|
||||
|
||||
Example:
|
||||
|
||||
```py
|
||||
def after_verification_request(user: UserDB, token: str, request: Request):
|
||||
print(f"Verification requested for user {user.id}. Verification token: {token}")
|
||||
|
||||
app.include_router(
|
||||
fastapi_users.get_verify_router("SECRET", after_verification_request=after_verification_request),
|
||||
prefix="/auth",
|
||||
tags=["auth"],
|
||||
)
|
||||
```
|
||||
|
||||
## After verification
|
||||
|
||||
You can provide a custom function to be called after a successful user verification. It is called with **two arguments**:
|
||||
|
||||
* The **user** that has been verified.
|
||||
* The original **`Request` object**.
|
||||
|
||||
This may be useful if you wish to send another e-mail or store this information in a data analytics or customer success platform.
|
||||
|
||||
You can define it as an `async` or standard method.
|
||||
|
||||
Example:
|
||||
|
||||
```py
|
||||
def after_verification(user: UserDB, request: Request):
|
||||
print(f"{user.id} is now verified.")
|
||||
|
||||
app.include_router(
|
||||
fastapi_users.get_verify_router("SECRET", after_verification=after_verification),
|
||||
fastapi_users.get_verify_router(),
|
||||
prefix="/auth",
|
||||
tags=["auth"],
|
||||
)
|
||||
|
||||
227
docs/configuration/user-manager.md
Normal file
227
docs/configuration/user-manager.md
Normal file
@@ -0,0 +1,227 @@
|
||||
# UserManager
|
||||
|
||||
The `UserManager` class is the core logic of FastAPI Users. We provide the `BaseUserManager` class which you should extend to set some parameters and define logic, for example when a user just registered or forgot its password.
|
||||
|
||||
It's designed to be easily extensible and customizable so that you can integrate less generic logic.
|
||||
|
||||
## Create your `UserManager` class
|
||||
|
||||
You should define your own version of the `UserManager` class to set various parameters.
|
||||
|
||||
```py hl_lines="13-29"
|
||||
{!./src/user_manager.py!}
|
||||
```
|
||||
|
||||
As you can see, you have to define here various attributes and methods. You can find the complete list of those below.
|
||||
|
||||
## Create `get_user_manager` dependency
|
||||
|
||||
The `UserManager` class will be injected at runtime using a FastAPI dependency. This way, you can run it in a database session or swap it with a mock during testing.
|
||||
|
||||
```py hl_lines="31-32"
|
||||
{!./src/user_manager.py!}
|
||||
```
|
||||
|
||||
Notice that we use the `get_user_db` dependency we defined earlier to inject the database instance.
|
||||
|
||||
## Customize attributes and methods
|
||||
|
||||
### Attributes
|
||||
|
||||
* `user_db_model`: Pydantic model of a DB representation of a user.
|
||||
* `reset_password_token_secret`: Secret to encode reset password token. **Use a strong passphrase and keep it secure.**
|
||||
* `reset_password_token_lifetime_seconds`: Lifetime of reset password token. Defaults to 3600.
|
||||
* `reset_password_token_audience`: JWT audience of reset password token. Defaults to `fastapi-users:reset`.
|
||||
* `verification_token_secret`: Secret to encode verification token. **Use a strong passphrase and keep it secure.**
|
||||
* `verification_token_lifetime_seconds`: Lifetime of verification token. Defaults to 3600.
|
||||
* `verification_token_audience`: JWT audience of verification token. Defaults to `fastapi-users:verify`.
|
||||
|
||||
### Methods
|
||||
|
||||
#### `validate_password`
|
||||
|
||||
Validate a password.
|
||||
|
||||
**Arguments**
|
||||
|
||||
* `password` (`str`): the password to validate.
|
||||
* `user` (`Union[UserCreate, User]`): user model which we are currently validating the password. Useful if you want to check that the password doesn't contain the name or the birthdate of the user for example.
|
||||
|
||||
**Output**
|
||||
|
||||
This function should return `None` if the password is valid or raise `InvalidPasswordException` if not. This exception expects an argument `reason` telling why the password is invalid. It'll be part of the error response.
|
||||
|
||||
**Example**
|
||||
|
||||
```py
|
||||
from fastapi_users import BaseUserManager, InvalidPasswordException
|
||||
|
||||
|
||||
class UserManager(BaseUserManager[UserCreate, UserDB]):
|
||||
# ...
|
||||
async def validate_password(
|
||||
self,
|
||||
password: str,
|
||||
user: Union[UserCreate, UserDB],
|
||||
) -> None:
|
||||
if len(password) < 8:
|
||||
raise InvalidPasswordException(
|
||||
reason="Password should be at least 8 characters"
|
||||
)
|
||||
if user.email in password:
|
||||
raise InvalidPasswordException(
|
||||
reason="Password should not contain e-mail"
|
||||
)
|
||||
```
|
||||
|
||||
#### `on_after_register`
|
||||
|
||||
Perform logic after successful user registration.
|
||||
|
||||
Typically, you'll want to **send a welcome e-mail** or add it to your marketing analytics pipeline.
|
||||
|
||||
**Arguments**
|
||||
|
||||
* `user` (`UserDB`): the registered user.
|
||||
* `request` (`Optional[Request]`): optional FastAPI request object that triggered the operation. Defaults to None.
|
||||
|
||||
**Example**
|
||||
|
||||
```py
|
||||
from fastapi_users import BaseUserManager
|
||||
|
||||
|
||||
class UserManager(BaseUserManager[UserCreate, UserDB]):
|
||||
# ...
|
||||
async def on_after_register(self, user: UserDB, request: Optional[Request] = None):
|
||||
print(f"User {user.id} has registered.")
|
||||
```
|
||||
|
||||
#### `on_after_update`
|
||||
|
||||
Perform logic after successful user update.
|
||||
|
||||
It may be useful, for example, if you wish to update your user in a data analytics or customer success platform.
|
||||
|
||||
**Arguments**
|
||||
|
||||
* `user` (`UserDB`): the updated user.
|
||||
* `update_dict` (`Dict[str, Any]`): dictionary with the updated user fields.
|
||||
* `request` (`Optional[Request]`): optional FastAPI request object that triggered the operation. Defaults to None.
|
||||
|
||||
**Example**
|
||||
|
||||
```py
|
||||
from fastapi_users import BaseUserManager
|
||||
|
||||
|
||||
class UserManager(BaseUserManager[UserCreate, UserDB]):
|
||||
# ...
|
||||
async def on_after_update(
|
||||
self,
|
||||
user: UserDB,
|
||||
update_dict: Dict[str, Any],
|
||||
request: Optional[Request] = None,
|
||||
):
|
||||
print(f"User {user.id} has been updated with {update_dict}.")
|
||||
```
|
||||
|
||||
#### `on_after_request_verify`
|
||||
|
||||
Perform logic after successful verification request.
|
||||
|
||||
Typically, you'll want to **send an e-mail** with the link (and the token) that allows the user to verify their e-mail.
|
||||
|
||||
**Arguments**
|
||||
|
||||
* `user` (`UserDB`): the user to verify.
|
||||
* `token` (`str`): the verification token.
|
||||
* `request` (`Optional[Request]`): optional FastAPI request object that triggered the operation. Defaults to None.
|
||||
|
||||
**Example**
|
||||
|
||||
```py
|
||||
from fastapi_users import BaseUserManager
|
||||
|
||||
|
||||
class UserManager(BaseUserManager[UserCreate, UserDB]):
|
||||
# ...
|
||||
async def on_after_request_verify(
|
||||
self, user: UserDB, token: str, request: Optional[Request] = None
|
||||
):
|
||||
print(f"Verification requested for user {user.id}. Verification token: {token}")
|
||||
```
|
||||
|
||||
#### `on_after_verify`
|
||||
|
||||
Perform logic after successful user verification.
|
||||
|
||||
This may be useful if you wish to send another e-mail or store this information in a data analytics or customer success platform.
|
||||
|
||||
**Arguments**
|
||||
|
||||
* `user` (`UserDB`): the verified user.
|
||||
* `request` (`Optional[Request]`): optional FastAPI request object that triggered the operation. Defaults to None.
|
||||
|
||||
**Example**
|
||||
|
||||
```py
|
||||
from fastapi_users import BaseUserManager
|
||||
|
||||
|
||||
class UserManager(BaseUserManager[UserCreate, UserDB]):
|
||||
# ...
|
||||
async def on_after_request_verify(
|
||||
self, user: UserDB, request: Optional[Request] = None
|
||||
):
|
||||
print(f"User {user.id} has been verified")
|
||||
```
|
||||
|
||||
#### `on_after_forgot_password`
|
||||
|
||||
Perform logic after successful forgot password request.
|
||||
|
||||
Typically, you'll want to **send an e-mail** with the link (and the token) that allows the user to reset their password.
|
||||
|
||||
**Arguments**
|
||||
|
||||
* `user` (`UserDB`): the user that forgot its password.
|
||||
* `token` (`str`): the forgot password token
|
||||
* `request` (`Optional[Request]`): optional FastAPI request object that triggered the operation. Defaults to None.
|
||||
|
||||
**Example**
|
||||
|
||||
```py
|
||||
from fastapi_users import BaseUserManager
|
||||
|
||||
|
||||
class UserManager(BaseUserManager[UserCreate, UserDB]):
|
||||
# ...
|
||||
async def on_after_request_verify(
|
||||
self, user: UserDB, token: str, request: Optional[Request] = None
|
||||
):
|
||||
print(f"User {user.id} has forgot their password. Reset token: {token}")
|
||||
```
|
||||
|
||||
#### `on_after_reset_password`
|
||||
|
||||
Perform logic after successful password reset.
|
||||
|
||||
For example, you may want to **send an e-mail** to the concerned user to warn him that their password has been changed and that they should take action if they think they have been hacked.
|
||||
|
||||
**Arguments**
|
||||
|
||||
* `user` (`UserDB`): the user that reset its password.
|
||||
* `request` (`Optional[Request]`): optional FastAPI request object that triggered the operation. Defaults to None.
|
||||
|
||||
**Example**
|
||||
|
||||
```py
|
||||
from fastapi_users import BaseUserManager
|
||||
|
||||
|
||||
class UserManager(BaseUserManager[UserCreate, UserDB]):
|
||||
# ...
|
||||
async def on_after_reset_password(self, user: UserDB, request: Optional[Request] = None):
|
||||
print(f"User {user.id} has reset their password.")
|
||||
```
|
||||
Reference in New Issue
Block a user