From 8b3367c7e4c1da4895e89ecdc137cc0c62bf4b4c Mon Sep 17 00:00:00 2001 From: zumuta Date: Sat, 23 Nov 2024 14:20:01 +0100 Subject: [PATCH] docs: add documentation for /api/v1/auth --- backend/docs/api/api_auth.md | 67 ++++++++++++--- .../src/kwai/api/v1/auth/endpoints/login.py | 86 ++++++++++--------- 2 files changed, 104 insertions(+), 49 deletions(-) diff --git a/backend/docs/api/api_auth.md b/backend/docs/api/api_auth.md index 0c44c90bb..3ce0da505 100644 --- a/backend/docs/api/api_auth.md +++ b/backend/docs/api/api_auth.md @@ -1,14 +1,61 @@ # Auth API's -## ::: kwai.api.v1.auth.endpoints.login - selection: - members: no -### ::: kwai.api.v1.auth.endpoints.login.login -### ::: kwai.api.v1.auth.endpoints.login.logout -### ::: kwai.api.v1.auth.endpoints.login.recover_user -### ::: kwai.api.v1.auth.endpoints.login.renew_access_token -### ::: kwai.api.v1.auth.endpoints.login.reset_password +All API's used for authentication, authorization, users, ... -# Auth Responses +## /api/v1/auth -### ::: kwai.api.v1.auth.endpoints.login.TokenSchema +### Requests + +::: kwai.api.v1.auth.endpoints.login.renew_access_token + options: + heading_level: 4 + +::: kwai.api.v1.auth.endpoints.login.login + options: + heading_level: 4 + +::: kwai.api.v1.auth.endpoints.login.logout + options: + heading_level: 4 + +::: kwai.api.v1.auth.endpoints.login.recover_user + options: + heading_level: 4 + +::: kwai.api.v1.auth.endpoints.login.reset_password + options: + heading_level: 4 + +### Responses + +#### ::: kwai.api.v1.auth.endpoints.login.TokenSchema + options: + show_root_toc_entry: false + +## /api/v1/user + +### Requests + +::: kwai.api.v1.auth.endpoints.user.get + options: + heading_level: 4 + +## /api/v1/user_invitations + +### Requests + +::: kwai.api.v1.auth.endpoints.user_invitations.create_user_invitation + options: + heading_level: 4 + +::: kwai.api.v1.auth.endpoints.user_invitations.delete_user_invitation + options: + heading_level: 4 + +::: kwai.api.v1.auth.endpoints.user_invitations.get_user_invitations + options: + heading_level: 4 + +::: kwai.api.v1.auth.endpoints.user_invitations.get_user_invitation + options: + heading_level: 4 diff --git a/backend/src/kwai/api/v1/auth/endpoints/login.py b/backend/src/kwai/api/v1/auth/endpoints/login.py index 5205a6a7d..dd2b74e7e 100644 --- a/backend/src/kwai/api/v1/auth/endpoints/login.py +++ b/backend/src/kwai/api/v1/auth/endpoints/login.py @@ -3,7 +3,7 @@ from typing import Annotated import jwt -from fastapi import APIRouter, Depends, Form, HTTPException, Response, status +from fastapi import APIRouter, Depends, Form, HTTPException, status from fastapi.security import OAuth2PasswordRequestForm from jwt import ExpiredSignatureError from loguru import logger @@ -73,6 +73,12 @@ class TokenSchema(BaseModel): @router.post( "/login", summary="Create access and refresh token for a user.", + responses={ + 200: {"description": "The user is logged in successfully."}, + 401: { + "description": "The email is invalid, authentication failed or user is unknown." + }, + }, ) async def login( settings: Annotated[Settings, Depends(get_settings)], @@ -81,15 +87,11 @@ async def login( ) -> TokenSchema: """Login a user. - The response is a TokenSchema. + This request expects a form (application/x-www-form-urlencoded). The form + must contain a `username` and `password` field. The username is + the email address of the user. - Note: - This request expects a form (application/x-www-form-urlencoded). - - Args: - settings: Settings dependency - db: Database dependency - form_data: Form data that contains the username and password + The response is a [TokenSchema][kwai.api.v1.auth.endpoints.login.TokenSchema]. """ command = AuthenticateUserCommand( username=form_data.username, @@ -120,7 +122,14 @@ async def login( return _encode_token(refresh_token, settings.security) -@router.post("/logout", summary="Logout the current user") +@router.post( + "/logout", + summary="Logout the current user", + responses={ + 200: {"description": "The user is logged out successfully."}, + 404: {"description": "The token is not found."}, + }, +) async def logout( settings: Annotated[Settings, Depends(get_settings)], db: Annotated[Database, Depends(create_database)], @@ -132,15 +141,8 @@ async def logout( A user is logged out by revoking the refresh token. The associated access token will also be revoked. - Args: - settings: Settings dependency - db: Database dependency - user: The currently logged-in user - refresh_token: The active refresh token of the user - - Returns: - Http code 200 on success, 401 when the user is not logged in, - 404 when the refresh token is not found. + This request expects a form (application/x-www-form-urlencoded). The form + must contain a **refresh_token** field. """ decoded_refresh_token = jwt.decode( refresh_token, @@ -162,6 +164,10 @@ async def logout( @router.post( "/access_token", summary="Renew an access token using a refresh token.", + responses={ + 200: {"description": "The access token is renewed."}, + 401: {"description": "The refresh token is expired."}, + }, ) async def renew_access_token( settings: Annotated[Settings, Depends(get_settings)], @@ -170,13 +176,12 @@ async def renew_access_token( ) -> TokenSchema: """Refresh the access token. - Args: - settings: Settings dependency - db: Database dependency - refresh_token: The active refresh token of the user + The response is a [TokenSchema][kwai.api.v1.auth.endpoints.login.TokenSchema]. - Returns: - TokenSchema: On success a new TokenSchema is returned. + When the refresh token is expired, the user needs to log in again. + + This request expects a form (application/x-www-form-urlencoded). The form + must contain a **refresh_token** field. """ try: decoded_refresh_token = jwt.decode( @@ -210,8 +215,9 @@ async def renew_access_token( @router.post( "/recover", summary="Initiate a password reset flow", - status_code=status.HTTP_200_OK, - response_class=Response, + responses={ + 200: {"description": "Ok."}, + }, ) async def recover_user( db: Annotated[Database, Depends(create_database)], @@ -222,13 +228,11 @@ async def recover_user( A mail with a unique id will be sent using the message bus. - Note: - To avoid leaking information, this api will always respond with 200 + This request expects a form (application/x-www-form-urlencoded). The form + must contain an **email** field. - Args: - email: The email of the user that wants to reset the password. - db: Database dependency - publisher: A publisher to publish the event + !!! Note + To avoid leaking information, this api will always respond with 200 """ command = RecoverUserCommand(email=email) try: @@ -244,7 +248,12 @@ async def recover_user( @router.post( "/reset", summary="Reset the password of a user.", - status_code=status.HTTP_200_OK, + responses={ # noqa B006 + 200: {"description": "The password is reset successfully."}, + 403: {"description": "This request is forbidden."}, + 404: {"description": "The uniqued id of the recovery could not be found."}, + 422: {"description": "The user could not be found."}, + }, ) async def reset_password( uuid: Annotated[str, Form()], @@ -253,13 +262,12 @@ async def reset_password( ): """Reset the password of the user. - Args: - uuid: The unique id of the password recovery. - password: The new password - db: Database dependency - Http code 200 on success, 404 when the unique is invalid, 422 when the request can't be processed, 403 when the request is forbidden. + + This request expects a form (application/x-www-form-urlencoded). The form + must contain an **uuid** and **password** field. The unique id must be still valid + and is retrieved by [/api/v1/auth/recover][post_/recover]. """ command = ResetPasswordCommand(uuid=uuid, password=password) try: