Skip to content

Commit bead189

Browse files
authored
Merge pull request #26 from Zerohertz/issue#22/feat/auth
[Feat] Auth domain development
2 parents 8ae5c48 + 9db6e67 commit bead189

File tree

36 files changed

+1221
-290
lines changed

36 files changed

+1221
-290
lines changed

.github/ISSUE_TEMPLATE/feature_request.yaml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ body:
2727
value: "The solution you're proposing."
2828
validations:
2929
required: true
30-
- type: textarea
31-
id: alternatives-considered
32-
attributes:
33-
label: Describe alternatives you've considered
34-
description: A clear and concise description of any alternative solutions or features you've considered.
35-
placeholder: Tell us about other alternatives you’ve thought about.
36-
value: "Alternatives you've considered."
30+
# - type: textarea
31+
# id: alternatives-considered
32+
# attributes:
33+
# label: Describe alternatives you've considered
34+
# description: A clear and concise description of any alternative solutions or features you've considered.
35+
# placeholder: Tell us about other alternatives you’ve thought about.
36+
# value: "Alternatives you've considered."
3737
- type: textarea
3838
id: additional-context
3939
attributes:

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
#### What this PR does / why we need it
1313

14+
- Description ({related|resolves|fixes: #})
15+
16+
<!--
1417
#### Which issue(s) this PR fixes
1518
1619
Fixes #
@@ -28,3 +31,4 @@ Fixes #
2831
```docs
2932
3033
```
34+
-->

app/api/v1/endpoints/admin/__init__.py

Whitespace-only changes.
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
from typing import Sequence
2+
3+
from dependency_injector.wiring import Provide, inject
4+
from fastapi import Depends
5+
from starlette import status
6+
7+
from app.core.auth import AdminDeps
8+
from app.core.container import Container
9+
from app.core.router import CoreAPIRouter
10+
from app.schemas.users import UserPatchRequest, UserRequest, UserResponse
11+
from app.services.users import UserService
12+
13+
router = CoreAPIRouter(prefix="/user", tags=["admin"], dependencies=[AdminDeps])
14+
15+
16+
@router.get(
17+
"/",
18+
response_model=Sequence[UserResponse],
19+
status_code=status.HTTP_200_OK,
20+
summary="",
21+
description="",
22+
)
23+
@inject
24+
async def get_users(
25+
service: UserService = Depends(Provide[Container.user_service]),
26+
):
27+
return await service.get_all()
28+
29+
30+
@router.get(
31+
"/{id}",
32+
response_model=UserResponse,
33+
status_code=status.HTTP_200_OK,
34+
summary="",
35+
description="",
36+
)
37+
@inject
38+
async def get_user(
39+
id: int,
40+
service: UserService = Depends(Provide[Container.user_service]),
41+
):
42+
return await service.get_by_id(id)
43+
44+
45+
@router.put(
46+
"/{id}",
47+
response_model=UserResponse,
48+
status_code=status.HTTP_200_OK,
49+
summary="",
50+
description="",
51+
)
52+
@inject
53+
async def put_user(
54+
id: int,
55+
user: UserRequest,
56+
service: UserService = Depends(Provide[Container.user_service]),
57+
):
58+
return await service.put_by_id(id=id, schema=user)
59+
60+
61+
@router.patch(
62+
"/{id}",
63+
response_model=UserResponse,
64+
status_code=status.HTTP_200_OK,
65+
summary="",
66+
description="",
67+
)
68+
@inject
69+
async def patch_user(
70+
id: int,
71+
user: UserPatchRequest,
72+
service: UserService = Depends(Provide[Container.user_service]),
73+
):
74+
return await service.patch_by_id(id=id, schema=user)
75+
76+
77+
@router.delete(
78+
"/{id}",
79+
response_model=UserResponse,
80+
status_code=status.HTTP_200_OK,
81+
summary="",
82+
description="",
83+
)
84+
@inject
85+
async def delete_user(
86+
id: int,
87+
service: UserService = Depends(Provide[Container.user_service]),
88+
):
89+
return await service.delete_by_id(id)

app/api/v1/endpoints/auth.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
from dependency_injector.wiring import Provide, inject
2+
from fastapi import Depends, Response
3+
from fastapi.responses import RedirectResponse
4+
from starlette import status
5+
6+
from app.core.auth import AuthDeps
7+
from app.core.configs import configs
8+
from app.core.container import Container
9+
from app.core.router import CoreAPIRouter
10+
from app.schemas.auth import JwtAccessToken, JwtRefreshToken, JwtToken
11+
from app.schemas.users import (
12+
UserOut,
13+
UserPasswordRequest,
14+
UserRegisterRequest,
15+
UserResponse,
16+
)
17+
from app.services.users import UserService
18+
19+
router = CoreAPIRouter(prefix="/auth", tags=["auth"])
20+
21+
22+
@router.post(
23+
"/refresh",
24+
response_model=JwtAccessToken,
25+
status_code=status.HTTP_200_OK,
26+
summary="",
27+
description="",
28+
)
29+
@inject
30+
async def post_refresh_token(
31+
token: JwtRefreshToken,
32+
service: UserService = Depends(Provide[Container.user_service]),
33+
):
34+
return await service.refresh(token)
35+
36+
37+
@router.post(
38+
"/register",
39+
response_model=UserResponse,
40+
status_code=status.HTTP_201_CREATED,
41+
summary="Register with password",
42+
description="",
43+
)
44+
@inject
45+
async def register_password(
46+
request: UserRegisterRequest,
47+
service: UserService = Depends(Provide[Container.user_service]),
48+
):
49+
return await service.register(request)
50+
51+
52+
@router.post(
53+
"/login",
54+
response_model=JwtToken,
55+
status_code=status.HTTP_200_OK,
56+
summary="Log in with password",
57+
description="",
58+
)
59+
@inject
60+
async def log_in_password(
61+
request: UserPasswordRequest,
62+
service: UserService = Depends(Provide[Container.user_service]),
63+
):
64+
return await service.log_in_password(schema=request)
65+
66+
67+
@router.get(
68+
"/oauth/login/github",
69+
response_model=Response,
70+
status_code=status.HTTP_302_FOUND,
71+
summary="Log in with GitHub OAuth",
72+
description="GitHub OAuth를 위해 redirection",
73+
)
74+
async def log_in_github():
75+
# NOTE: &scope=repo,user
76+
# TODO: APIResponse (related: #24)
77+
return RedirectResponse(
78+
f"https://github.com/login/oauth/authorize?client_id={configs.GITHUB_OAUTH_CLIENT_ID}"
79+
)
80+
81+
82+
@router.get(
83+
"/oauth/callback/github",
84+
response_model=JwtToken,
85+
status_code=status.HTTP_200_OK,
86+
summary="Callback for GitHub OAuth",
87+
description="GitHub OAuth에 의해 redirection될 endpoint",
88+
include_in_schema=False,
89+
)
90+
@inject
91+
async def callback_github(
92+
code: str,
93+
service: UserService = Depends(Provide[Container.user_service]),
94+
):
95+
"""
96+
# NOTE: Cookie 방식으로 JWT token 사용 시
97+
response.set_cookie(
98+
key="access_token", value=jwt_token.access_token, httponly=True, secure=True
99+
)
100+
response.set_cookie(
101+
key="refresh_token", value=jwt_token.refresh_token, httponly=True, secure=True
102+
)
103+
"""
104+
return await service.log_in_github(code=code)
105+
106+
107+
@router.get(
108+
"/me",
109+
response_model=UserOut,
110+
status_code=status.HTTP_200_OK,
111+
summary="",
112+
description="",
113+
)
114+
async def get_me(user: AuthDeps):
115+
return user

app/api/v1/endpoints/users.py

Lines changed: 16 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,86 +2,57 @@
22
from fastapi import Depends
33
from starlette import status
44

5+
from app.core.auth import AuthDeps
56
from app.core.container import Container
67
from app.core.router import CoreAPIRouter
7-
from app.schemas.users import UserCreateRequest, UserCreateResponse
8+
from app.schemas.users import UserPatchRequest, UserRequest, UserResponse
89
from app.services.users import UserService
910

1011
router = CoreAPIRouter(prefix="/user", tags=["user"])
1112

1213

13-
@router.post(
14-
"",
15-
response_model=UserCreateResponse,
16-
status_code=status.HTTP_201_CREATED,
17-
summary="",
18-
description="",
19-
)
20-
@inject
21-
async def create_user(
22-
user: UserCreateRequest,
23-
service: UserService = Depends(Provide[Container.user_service]),
24-
):
25-
return await service.create(user)
26-
27-
28-
@router.get(
29-
"/{id}",
30-
response_model=UserCreateResponse,
31-
status_code=status.HTTP_200_OK,
32-
summary="",
33-
description="",
34-
)
35-
@inject
36-
async def get_user(
37-
id: int,
38-
service: UserService = Depends(Provide[Container.user_service]),
39-
):
40-
return await service.get_by_id(id)
41-
42-
4314
@router.put(
44-
"/{id}",
45-
response_model=UserCreateResponse,
15+
"/",
16+
response_model=UserResponse,
4617
status_code=status.HTTP_200_OK,
4718
summary="",
4819
description="",
4920
)
5021
@inject
5122
async def put_user(
52-
id: int,
53-
user: UserCreateRequest,
23+
user: AuthDeps,
24+
schema: UserRequest,
5425
service: UserService = Depends(Provide[Container.user_service]),
5526
):
56-
return await service.put_by_id(id=id, schema=user)
27+
return await service.put_by_id(id=user.id, schema=schema)
5728

5829

5930
@router.patch(
60-
"/{id}",
61-
response_model=UserCreateResponse,
31+
"/",
32+
response_model=UserResponse,
6233
status_code=status.HTTP_200_OK,
6334
summary="",
6435
description="",
6536
)
6637
@inject
6738
async def patch_user(
68-
id: int,
69-
user: UserCreateRequest,
39+
user: AuthDeps,
40+
schema: UserPatchRequest,
7041
service: UserService = Depends(Provide[Container.user_service]),
7142
):
72-
return await service.patch_by_id(id=id, schema=user)
43+
return await service.patch_by_id(id=user.id, schema=schema)
7344

7445

7546
@router.delete(
76-
"/{id}",
77-
response_model=UserCreateResponse,
47+
"/",
48+
response_model=UserResponse,
7849
status_code=status.HTTP_200_OK,
7950
summary="",
8051
description="",
8152
)
8253
@inject
8354
async def delete_user(
84-
id: int,
55+
user: AuthDeps,
8556
service: UserService = Depends(Provide[Container.user_service]),
8657
):
87-
return await service.delete_by_id(id)
58+
return await service.delete_by_id(id=user.id)

app/api/v1/routers.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from fastapi import APIRouter
22

3-
from app.api.v1.endpoints import shields, users
3+
from app.api.v1.endpoints import auth, shields, users
4+
from app.api.v1.endpoints.admin import users as admin_users
45

56
routers = APIRouter(prefix="/v1", tags=["v1"])
6-
_routers = [users.router, shields.router]
7+
_routers = [auth.router, users.router, shields.router] + [admin_users.router]
78

89
for _router in _routers:
910
routers.include_router(_router)

0 commit comments

Comments
 (0)