Skip to content

Commit

Permalink
feat(security): add oauth
Browse files Browse the repository at this point in the history
  • Loading branch information
Deo committed May 12, 2020
1 parent df54a04 commit 47f8c38
Show file tree
Hide file tree
Showing 16 changed files with 265 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Expand Up @@ -16,7 +16,7 @@
"console": "integratedTerminal",
"subProcess": true,
"env": {
"CORS_ALLOWS": "'[\"http://127.0.0.1\"]'",
"TODO_CORS_ALLOWS": "'[\"http://127.0.0.1\"]'",
}
}
]
Expand Down
30 changes: 21 additions & 9 deletions .vscode/settings.json
Expand Up @@ -9,18 +9,30 @@
"**/.benchmarks": true,
"**/.venv": true,
"**/node_modules": true,
"**/__pycache__": true,
"**/.pytest_cache": true
"**/public": true
},
"editor.detectIndentation": false,
"editor.formatOnSave": true,
"python.linting.pylintEnabled": false,
"python.linting.mypyEnabled": true,
"python.linting.enabled": true,
"editor.insertSpaces": true,
"editor.tabSize": 4,
"python.pythonPath": ".venv/bin/python",
"python.envFile": "${workspaceFolder}/.env",
"python.testing.pytestEnabled": true,
"python.formatting.provider": "black",
"python.linting.enabled": true,
"python.linting.lintOnSave": true,
"python.linting.mypyEnabled": true,
"python.linting.pycodestyleArgs": [
"--max-line-length=80"
],
"python.linting.pycodestyleEnabled": true,
"python.linting.pylintEnabled": true,
"python.linting.pylintArgs": [
"--errors-only", // mypy, pycodestyle
"--disable=no-member", // mypy
"--enable=unused-import" // 이것 때문에 씀..
],
"python.formatting.blackArgs": [
"--line-length=80"
],
"pythonTestExplorer.testFramework": "pytest",
"python.testing.pytestEnabled": true,
"editor.fontFamily": "D2Coding"
]
}
3 changes: 3 additions & 0 deletions Pipfile
Expand Up @@ -21,8 +21,11 @@ pylint = "*"
black = "==19.3b0"

[packages]
# web framework
fastapi = "*"
# asgi
uvicorn = "*"
python-multipart = "*"

[requires]
python_version = "3.8"
34 changes: 24 additions & 10 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions requirements.txt
Expand Up @@ -4,6 +4,8 @@ fastapi==0.54.1
h11==0.9.0
httptools==0.1.1 ; sys_platform != 'win32' and sys_platform != 'cygwin' and platform_python_implementation != 'PyPy'
pydantic==1.5.1
python-multipart==0.0.5
six==1.14.0
starlette==0.13.2
uvicorn==0.11.5
uvloop==0.14.0 ; sys_platform != 'win32' and sys_platform != 'cygwin' and platform_python_implementation != 'PyPy'
Expand Down
6 changes: 6 additions & 0 deletions src/config.py
Expand Up @@ -13,6 +13,11 @@ class Settings(BaseSettings):
"""

API_VERSION_PREFIX: str = "/api/v1"
SECRET_KEY: str = "have to change secret key"
JWT_ALGORITHM: str = "HS256"

ACCESS_TOKEN_EXPIRE_SECONDS: int = 86400 * 7

CORS_ALLOWS: List[HttpUrl] = []

@validator("CORS_ALLOWS", pre=True)
Expand All @@ -28,6 +33,7 @@ def __set_cors_allows(cls, v: Union[str, List[str]]) -> List[str]: # noqa
class Config:
""" setting의 부가 설정 """

env_prefix = "TODO_"
case_sensitive = True


Expand Down
12 changes: 12 additions & 0 deletions src/constants.py
@@ -0,0 +1,12 @@
"""
constants
"""
from enum import IntEnum


class UserPermission(IntEnum):
""" 유저 권한 """

GUEST = 0
NORMAL = 1
ADMIN = 2
3 changes: 2 additions & 1 deletion src/main.py
Expand Up @@ -4,7 +4,7 @@
from fastapi.applications import FastAPI
from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException
from .routes import api_v1
from .routes import api_v1, token_router
from .errors import http_exception_handler, validation_exception_handler
from .config import settings

Expand All @@ -23,3 +23,4 @@ def create_app() -> FastAPI:

app = create_app()
app.include_router(api_v1, prefix=f"{settings.API_VERSION_PREFIX}")
app.include_router(token_router, prefix="/api/token", tags=["auth"])
4 changes: 3 additions & 1 deletion src/routes/__init__.py
Expand Up @@ -5,10 +5,12 @@

from .health import health as health_router
from .todos import todos as todos_router
from .token import token as token_router

__all__ = ["api_v1", "health_router", "todos_router"]
__all__ = ["api_v1", "health_router", "todos_router", "token_router"]

api_v1 = APIRouter()


api_v1.include_router(health_router, prefix="/health", tags=["manage"])
api_v1.include_router(todos_router, prefix="/todos", tags=["todos"])
24 changes: 18 additions & 6 deletions src/routes/todos.py
Expand Up @@ -4,10 +4,11 @@
from typing import Optional, List, Dict

from fastapi.routing import APIRouter
from fastapi.param_functions import Path
from fastapi.param_functions import Path, Depends
from fastapi.exceptions import HTTPException
from fastapi import status
from pydantic import BaseModel
from .token import get_current_active_user, User

todos = APIRouter()

Expand Down Expand Up @@ -47,10 +48,13 @@ def __get_last_seqno() -> int:


__valid_seqno = Path(..., ge=1)
__current_active_user = Depends(get_current_active_user)


@todos.get(path="/{seqno}", response_model=TodoItem)
async def get_todo(seqno: int = __valid_seqno) -> TodoItem:
async def get_todo(
seqno: int = __valid_seqno, current_user: User = __current_active_user
) -> TodoItem:
""" get todo item """
return __get_todo(seqno=seqno)

Expand All @@ -63,7 +67,9 @@ def __get_todo(seqno: int) -> TodoItem:


@todos.get("", response_model=List[TodoItem])
async def get_todos() -> List[TodoItem]:
async def get_todos(
current_user: User = __current_active_user
) -> List[TodoItem]:
""" get todos """
return __get_all()

Expand All @@ -78,7 +84,9 @@ def __get_all() -> List[TodoItem]:


@todos.post("", status_code=status.HTTP_201_CREATED, response_model=TodoItem)
async def create_todo(todo: TodoCreateRequest) -> TodoItem:
async def create_todo(
todo: TodoCreateRequest, current_user: User = __current_active_user
) -> TodoItem:
""" create todo """
return __create_todo(todo)

Expand All @@ -94,7 +102,9 @@ def __create_todo(todo: TodoCreateRequest) -> TodoItem:
path="/{seqno}", status_code=status.HTTP_200_OK, response_model=TodoItem
)
async def update_todo(
todo_update_request: TodoUpdateRequest, seqno: int = __valid_seqno
todo_update_request: TodoUpdateRequest,
seqno: int = __valid_seqno,
current_user: User = __current_active_user,
) -> TodoItem:
""" update todo """
todo = __get_todo(seqno=seqno)
Expand All @@ -119,7 +129,9 @@ def __update_todo(


@todos.delete(path="/{seqno}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_todo(seqno: int = __valid_seqno) -> None:
async def delete_todo(
seqno: int = __valid_seqno, current_user: User = __current_active_user
) -> None:
""" delete todo """
todo = __get_todo(seqno)
__fake_todos.pop(todo.seqno)
Expand Down

0 comments on commit 47f8c38

Please sign in to comment.