diff --git a/app/__pycache__/__init__.cpython-313.pyc b/app/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..b530c48 Binary files /dev/null and b/app/__pycache__/__init__.cpython-313.pyc differ diff --git a/app/__pycache__/app.cpython-313.pyc b/app/__pycache__/app.cpython-313.pyc new file mode 100644 index 0000000..8bc31a6 Binary files /dev/null and b/app/__pycache__/app.cpython-313.pyc differ diff --git a/app/__pycache__/deps.cpython-313.pyc b/app/__pycache__/deps.cpython-313.pyc new file mode 100644 index 0000000..0d17fdb Binary files /dev/null and b/app/__pycache__/deps.cpython-313.pyc differ diff --git a/app/__pycache__/schemas.cpython-313.pyc b/app/__pycache__/schemas.cpython-313.pyc new file mode 100644 index 0000000..43f726c Binary files /dev/null and b/app/__pycache__/schemas.cpython-313.pyc differ diff --git a/app/__pycache__/store.cpython-313.pyc b/app/__pycache__/store.cpython-313.pyc new file mode 100644 index 0000000..26ee431 Binary files /dev/null and b/app/__pycache__/store.cpython-313.pyc differ diff --git a/app/__pycache__/utils.cpython-313.pyc b/app/__pycache__/utils.cpython-313.pyc new file mode 100644 index 0000000..f825546 Binary files /dev/null and b/app/__pycache__/utils.cpython-313.pyc differ diff --git a/app/app.py b/app/app.py index ccc483b..aa50152 100644 --- a/app/app.py +++ b/app/app.py @@ -1,6 +1,6 @@ from fastapi import FastAPI, status, HTTPException, Depends from fastapi.responses import RedirectResponse -from app.schemas import UserOut, UserAuth, TokenSchema +from app.schemas import UserOut, UserAuth, TokenSchema, SystemUser from fastapi.security import OAuth2PasswordRequestForm from app.utils import ( get_hashed_password, @@ -8,15 +8,15 @@ create_refresh_token, verify_password ) +from app.store import users_db +from app.deps import get_current_user from uuid import uuid4 app = FastAPI() -users_db = {} @app.post('/signup', summary="Create new user", response_model=UserOut) async def create_user(data: UserAuth): - # querying database to check if user already exist user = users_db.get(data.email, None) if user is not None: raise HTTPException( @@ -29,7 +29,7 @@ async def create_user(data: UserAuth): 'id': str(uuid4()), "username": data.username } - users_db[data.email] = user # saving user to database + users_db[data.email] = user return UserOut(id=user["id"], email=user["email"], username=user["username"]) @@ -53,6 +53,7 @@ async def login(form_data: OAuth2PasswordRequestForm = Depends()): return { "access_token": create_access_token(user['email']), "refresh_token": create_refresh_token(user['email']), + "token_type": "bearer", } @app.get("/users", response_model=list[UserOut]) @@ -65,3 +66,7 @@ async def get_users(): } for user in users_db.values() ] + +@app.get("/me", response_model=UserOut, summary="Get current logged in user") +async def get_me(current_user: SystemUser = Depends(get_current_user)): + return UserOut(id=current_user.id, username=current_user.username, email=current_user.email) \ No newline at end of file diff --git a/app/deps.py b/app/deps.py index 69700eb..520ba45 100644 --- a/app/deps.py +++ b/app/deps.py @@ -4,13 +4,13 @@ from fastapi.security import OAuth2PasswordBearer from .utils import ( ALGORITHM, - JWT_SECRET_KEY + SECRET_KEY ) from jose import jwt from pydantic import ValidationError from app.schemas import TokenPayload, SystemUser -from .app import users_db # importing the user dictionary from app/app.py +from .store import users_db reuseable_oauth = OAuth2PasswordBearer( tokenUrl="/login", @@ -21,7 +21,7 @@ async def get_current_user(token: str = Depends(reuseable_oauth)) -> SystemUser: try: payload = jwt.decode( - token, JWT_SECRET_KEY, algorithms=[ALGORITHM] + token, SECRET_KEY, algorithms=[ALGORITHM] ) token_data = TokenPayload(**payload) @@ -40,7 +40,6 @@ async def get_current_user(token: str = Depends(reuseable_oauth)) -> SystemUser: user: Union[dict[str, Any], None] = users_db.get(token_data.sub, None) - if user is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, diff --git a/app/schemas.py b/app/schemas.py index cd47e02..ad17aee 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -3,7 +3,7 @@ class UserAuth(BaseModel): """Schema that is used for user input during signup or login.""" username: str = Field(min_length=3, max_length=30) - email: str = EmailStr + email: EmailStr password: str = Field(min_length=6, max_length=100) @@ -16,4 +16,17 @@ class UserOut(BaseModel): class TokenSchema(BaseModel): access_token: str - token_type: str = "bearer" \ No newline at end of file + refresh_token: str + token_type: str = "bearer" + + +class TokenPayload(BaseModel): + sub: str + exp: int + + +class SystemUser(BaseModel): + id: str + username: str + email: str + password: str \ No newline at end of file diff --git a/app/store.py b/app/store.py new file mode 100644 index 0000000..a114bf9 --- /dev/null +++ b/app/store.py @@ -0,0 +1 @@ +users_db = {} \ No newline at end of file diff --git a/app/utils.py b/app/utils.py index 9348b17..557c37e 100644 --- a/app/utils.py +++ b/app/utils.py @@ -26,7 +26,7 @@ def verify_password(password: str, hashed_pass: str) -> bool: match or not.""" return password_context.verify(password, hashed_pass) -def create_access_token(subject: Union[str, Any], expires_delta: int = None)->str: +def create_access_token(subject: Union[str, Any], expires_delta: timedelta = None)->str: if expires_delta is not None: expires_delta = datetime.utcnow() + expires_delta else: @@ -39,7 +39,7 @@ def create_access_token(subject: Union[str, Any], expires_delta: int = None)->st ALGORITHM) return encoded_jwt -def create_refresh_token(subject: Union[str, Any], expires_delta: int = None) -> str: +def create_refresh_token(subject: Union[str, Any], expires_delta: timedelta = None) -> str: if expires_delta is not None: expires_delta = datetime.utcnow() + expires_delta else: