|
| 1 | +from typing import Annotated |
| 2 | + |
1 | 3 | from dependency_injector.wiring import Provide, inject |
2 | | -from fastapi import Depends, status |
3 | | -from fastapi.responses import JSONResponse, RedirectResponse |
| 4 | +from fastapi import Depends, Form, status |
| 5 | +from fastapi.responses import JSONResponse |
4 | 6 |
|
5 | | -from app.core.auth import AuthDeps |
6 | | -from app.core.configs import configs |
| 7 | +from app.core.auth import GitHubOAuthDeps, PasswordOAuthDeps, UserAuthDeps |
7 | 8 | from app.core.container import Container |
8 | 9 | from app.core.router import CoreAPIRouter |
9 | | -from app.schemas.auth import JwtAccessToken, JwtRefreshToken, JwtToken |
10 | | -from app.schemas.users import ( |
11 | | - UserOut, |
12 | | - UserPasswordRequest, |
13 | | - UserRegisterRequest, |
14 | | - UserResponse, |
| 10 | +from app.schemas.auth import ( |
| 11 | + GitHubOAuthRequest, |
| 12 | + JwtToken, |
| 13 | + PasswordOAuthReigsterRequest, |
| 14 | + PasswordOAuthRequest, |
| 15 | + RefreshOAuthRequest, |
15 | 16 | ) |
| 17 | +from app.schemas.users import UserOut, UserResponse |
16 | 18 | from app.services.users import UserService |
17 | 19 |
|
18 | 20 | router = CoreAPIRouter(prefix="/auth", tags=["auth"]) |
19 | 21 |
|
20 | 22 |
|
21 | 23 | @router.post( |
22 | 24 | "/refresh", |
23 | | - response_model=JwtAccessToken, |
| 25 | + response_model=JwtToken, |
24 | 26 | response_class=JSONResponse, |
25 | 27 | status_code=status.HTTP_200_OK, |
26 | | - summary="", |
27 | | - description="", |
| 28 | + summary="Refresh access token", |
| 29 | + description="- Refresh the access token using a valid refresh token.</br>\n" |
| 30 | + "- If the refresh token is invalid or expired, authentication will fail.", |
28 | 31 | ) |
29 | 32 | @inject |
30 | | -async def post_refresh_token( |
31 | | - token: JwtRefreshToken, |
| 33 | +async def refresh( |
| 34 | + request: Annotated[RefreshOAuthRequest, Form(...)], |
32 | 35 | service: UserService = Depends(Provide[Container.user_service]), |
33 | 36 | ): |
34 | | - return await service.refresh(token) |
| 37 | + return await service.refresh(request) |
35 | 38 |
|
36 | 39 |
|
37 | 40 | @router.post( |
38 | | - "/register", |
| 41 | + "/register/password", |
39 | 42 | response_model=UserResponse, |
40 | 43 | response_class=JSONResponse, |
41 | 44 | status_code=status.HTTP_201_CREATED, |
42 | | - summary="Register with password", |
43 | | - description="", |
| 45 | + summary="Register a new account with a password", |
| 46 | + description="- Create a new user account using an email and password.</br>\n" |
| 47 | + "- The provided credentials will be used for authentication.", |
44 | 48 | ) |
45 | 49 | @inject |
46 | 50 | async def register_password( |
47 | | - request: UserRegisterRequest, |
| 51 | + request: Annotated[PasswordOAuthReigsterRequest, Form(...)], |
48 | 52 | service: UserService = Depends(Provide[Container.user_service]), |
49 | 53 | ): |
50 | 54 | return await service.register(request) |
51 | 55 |
|
52 | 56 |
|
53 | 57 | @router.post( |
54 | | - "/login", |
| 58 | + "/token/password", |
55 | 59 | response_model=JwtToken, |
56 | 60 | response_class=JSONResponse, |
57 | 61 | status_code=status.HTTP_200_OK, |
58 | | - summary="Log in with password", |
59 | | - description="", |
| 62 | + summary="Obtain an access token via password authentication", |
| 63 | + description="- Authenticate using an email and password to obtain an access token.</br>\n" |
| 64 | + "- This token can be used for subsequent API requests.", |
60 | 65 | ) |
61 | 66 | @inject |
62 | 67 | async def log_in_password( |
63 | | - request: UserPasswordRequest, |
| 68 | + # NOTE: OAuth2PasswordRequestForm |
| 69 | + request: Annotated[PasswordOAuthRequest, Form(...)], |
64 | 70 | service: UserService = Depends(Provide[Container.user_service]), |
65 | 71 | ): |
66 | 72 | return await service.log_in_password(schema=request) |
67 | 73 |
|
68 | 74 |
|
69 | | -@router.get( |
70 | | - "/oauth/login/github", |
71 | | - response_model=None, |
72 | | - response_class=RedirectResponse, |
73 | | - status_code=status.HTTP_302_FOUND, |
74 | | - summary="Log in with GitHub OAuth", |
75 | | - description="GitHub OAuth를 위해 redirection", |
76 | | -) |
77 | | -async def log_in_github(): |
78 | | - # NOTE: &scope=repo,user |
79 | | - return RedirectResponse( |
80 | | - f"https://github.com/login/oauth/authorize?client_id={configs.GITHUB_OAUTH_CLIENT_ID}" |
81 | | - ) |
82 | | - |
83 | | - |
84 | | -@router.get( |
85 | | - "/oauth/callback/github", |
| 75 | +@router.post( |
| 76 | + "/token/github", |
86 | 77 | response_model=JwtToken, |
87 | 78 | response_class=JSONResponse, |
88 | 79 | status_code=status.HTTP_200_OK, |
89 | | - summary="Callback for GitHub OAuth", |
90 | | - description="GitHub OAuth에 의해 redirection될 endpoint", |
91 | | - include_in_schema=False, |
| 80 | + summary="Obtain an access token via GitHub OAuth", |
| 81 | + description="- Authenticate using GitHub OAuth and receive an access token.<br/>\n" |
| 82 | + "- The client must provide an authorization code obtained from GitHub.", |
92 | 83 | ) |
93 | 84 | @inject |
94 | | -async def callback_github( |
95 | | - code: str, |
| 85 | +async def log_in_github( |
| 86 | + request: Annotated[GitHubOAuthRequest, Form()], |
96 | 87 | service: UserService = Depends(Provide[Container.user_service]), |
97 | 88 | ): |
98 | | - """ |
99 | | - # NOTE: Cookie 방식으로 JWT token 사용 시 |
100 | | - response.set_cookie( |
101 | | - key="access_token", value=jwt_token.access_token, httponly=True, secure=True |
102 | | - ) |
103 | | - response.set_cookie( |
104 | | - key="refresh_token", value=jwt_token.refresh_token, httponly=True, secure=True |
105 | | - ) |
106 | | - """ |
107 | | - return await service.log_in_github(code=code) |
| 89 | + return await service.log_in_github(request) |
108 | 90 |
|
109 | 91 |
|
110 | 92 | @router.get( |
111 | 93 | "/me", |
112 | 94 | response_model=UserOut, |
113 | 95 | response_class=JSONResponse, |
114 | 96 | status_code=status.HTTP_200_OK, |
115 | | - summary="", |
116 | | - description="", |
| 97 | + dependencies=[PasswordOAuthDeps, GitHubOAuthDeps], |
| 98 | + summary="Retrieve the current authenticated user's information", |
| 99 | + description="- Returns the authenticated user's details based on the provided access token.</br>\n" |
| 100 | + "- Requires a valid token obtained via password authentication or GitHub OAuth.", |
117 | 101 | ) |
118 | | -async def get_me(user: AuthDeps): |
| 102 | +async def get_me(user: Annotated[UserOut, UserAuthDeps]): |
119 | 103 | return user |
0 commit comments