mirror of
				https://github.com/fastapi-users/fastapi-users.git
				synced 2025-10-31 17:38:30 +08:00 
			
		
		
		
	Add Request in event_handlers arguments
This commit is contained in:
		| @ -42,7 +42,7 @@ In order to be as unopinionated as possible, we expose decorators that allow you | |||||||
|  |  | ||||||
| ### After register | ### After register | ||||||
|  |  | ||||||
| This event handler is called after a successful registration. It is called with **one argument**: the **user** that has just registered. | This event handler is called after a successful registration. It is called with **two argument**: 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. | Typically, you'll want to **send a welcome e-mail** or add it to your marketing analytics pipeline. | ||||||
|  |  | ||||||
| @ -52,13 +52,17 @@ Example: | |||||||
|  |  | ||||||
| ```py | ```py | ||||||
| @fastapi_users.on_after_register() | @fastapi_users.on_after_register() | ||||||
| def on_after_register(user: User): | def on_after_register(user: User, request: Request): | ||||||
|     print(f"User {user.id} has registered.") |     print(f"User {user.id} has registered.") | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ### After forgot password | ### After forgot password | ||||||
|  |  | ||||||
| This event handler is called after a successful forgot password request. It is called with **two arguments**: the **user** which has requested to reset their password and a ready-to-use **JWT token** that will be accepted by the reset password route. | This event handler is 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. | Typically, you'll want to **send an e-mail** with the link (and the token) that allows the user to reset their password. | ||||||
|  |  | ||||||
| @ -68,7 +72,7 @@ Example: | |||||||
|  |  | ||||||
| ```py | ```py | ||||||
| @fastapi_users.on_after_forgot_password() | @fastapi_users.on_after_forgot_password() | ||||||
| def on_after_forgot_password(user: User, token: str): | def on_after_forgot_password(user: User, token: str, request: Request): | ||||||
|     print(f"User {user.id} has forgot their password. Reset token: {token}") |     print(f"User {user.id} has forgot their password. Reset token: {token}") | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ from fastapi import Body, Depends, HTTPException | |||||||
| from fastapi.security import OAuth2PasswordRequestForm | from fastapi.security import OAuth2PasswordRequestForm | ||||||
| from pydantic import EmailStr | from pydantic import EmailStr | ||||||
| from starlette import status | from starlette import status | ||||||
|  | from starlette.requests import Request | ||||||
| from starlette.responses import Response | from starlette.responses import Response | ||||||
|  |  | ||||||
| from fastapi_users import models | from fastapi_users import models | ||||||
| @ -74,7 +75,7 @@ def get_user_router( | |||||||
|     @router.post( |     @router.post( | ||||||
|         "/register", response_model=user_model, status_code=status.HTTP_201_CREATED |         "/register", response_model=user_model, status_code=status.HTTP_201_CREATED | ||||||
|     ) |     ) | ||||||
|     async def register(user: user_create_model):  # type: ignore |     async def register(request: Request, user: user_create_model):  # type: ignore | ||||||
|         user = cast(models.BaseUserCreate, user)  # Prevent mypy complain |         user = cast(models.BaseUserCreate, user)  # Prevent mypy complain | ||||||
|         existing_user = await user_db.get_by_email(user.email) |         existing_user = await user_db.get_by_email(user.email) | ||||||
|  |  | ||||||
| @ -90,12 +91,14 @@ def get_user_router( | |||||||
|         ) |         ) | ||||||
|         created_user = await user_db.create(db_user) |         created_user = await user_db.create(db_user) | ||||||
|  |  | ||||||
|         await router.run_handlers(Event.ON_AFTER_REGISTER, created_user) |         await router.run_handlers(Event.ON_AFTER_REGISTER, created_user, request) | ||||||
|  |  | ||||||
|         return created_user |         return created_user | ||||||
|  |  | ||||||
|     @router.post("/forgot-password", status_code=status.HTTP_202_ACCEPTED) |     @router.post("/forgot-password", status_code=status.HTTP_202_ACCEPTED) | ||||||
|     async def forgot_password(email: EmailStr = Body(..., embed=True)): |     async def forgot_password( | ||||||
|  |         request: Request, email: EmailStr = Body(..., embed=True) | ||||||
|  |     ): | ||||||
|         user = await user_db.get_by_email(email) |         user = await user_db.get_by_email(email) | ||||||
|  |  | ||||||
|         if user is not None and user.is_active: |         if user is not None and user.is_active: | ||||||
| @ -105,7 +108,9 @@ def get_user_router( | |||||||
|                 reset_password_token_lifetime_seconds, |                 reset_password_token_lifetime_seconds, | ||||||
|                 reset_password_token_secret, |                 reset_password_token_secret, | ||||||
|             ) |             ) | ||||||
|             await router.run_handlers(Event.ON_AFTER_FORGOT_PASSWORD, user, token) |             await router.run_handlers( | ||||||
|  |                 Event.ON_AFTER_FORGOT_PASSWORD, user, token, request | ||||||
|  |             ) | ||||||
|  |  | ||||||
|         return None |         return None | ||||||
|  |  | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ import jwt | |||||||
| import pytest | import pytest | ||||||
| from fastapi import FastAPI | from fastapi import FastAPI | ||||||
| from starlette import status | from starlette import status | ||||||
|  | from starlette.requests import Request | ||||||
| from starlette.testclient import TestClient | from starlette.testclient import TestClient | ||||||
|  |  | ||||||
| from fastapi_users.authentication import Authenticator | from fastapi_users.authentication import Authenticator | ||||||
| @ -106,6 +107,8 @@ class TestRegister: | |||||||
|  |  | ||||||
|         actual_user = event_handler.call_args[0][0] |         actual_user = event_handler.call_args[0][0] | ||||||
|         assert actual_user.id == response_json["id"] |         assert actual_user.id == response_json["id"] | ||||||
|  |         request = event_handler.call_args[0][1] | ||||||
|  |         assert isinstance(request, Request) | ||||||
|  |  | ||||||
|     def test_valid_body_is_superuser(self, test_app_client: TestClient, event_handler): |     def test_valid_body_is_superuser(self, test_app_client: TestClient, event_handler): | ||||||
|         json = { |         json = { | ||||||
| @ -211,6 +214,8 @@ class TestForgotPassword: | |||||||
|             algorithms=[JWT_ALGORITHM], |             algorithms=[JWT_ALGORITHM], | ||||||
|         ) |         ) | ||||||
|         assert decoded_token["user_id"] == user.id |         assert decoded_token["user_id"] == user.id | ||||||
|  |         request = event_handler.call_args[0][2] | ||||||
|  |         assert isinstance(request, Request) | ||||||
|  |  | ||||||
|  |  | ||||||
| @pytest.mark.router | @pytest.mark.router | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 François Voron
					François Voron