Compare commits
2 Commits
9099120ee2
...
cd51902313
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd51902313 | ||
|
|
8620e9b5a1 |
@@ -1,10 +1,12 @@
|
|||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends
|
from fastapi import APIRouter, Depends, Response
|
||||||
from fastapi.security import OAuth2PasswordRequestForm
|
from fastapi.security import OAuth2PasswordRequestForm
|
||||||
|
|
||||||
from src.api.dependacies.db_dep import sessionDep
|
from src.api.dependacies.db_dep import sessionDep
|
||||||
|
from src.api.dependacies.user_dep import ActiveUser
|
||||||
from src.core.settings import settings
|
from src.core.settings import settings
|
||||||
|
from src.schemas.auth import Token
|
||||||
from src.schemas.users import UserRequestADD
|
from src.schemas.users import UserRequestADD
|
||||||
from src.services.auth import AuthService
|
from src.services.auth import AuthService
|
||||||
|
|
||||||
@@ -17,12 +19,26 @@ async def registration(session: sessionDep, credential: UserRequestADD):
|
|||||||
return auth
|
return auth
|
||||||
|
|
||||||
|
|
||||||
@router.post(path="/login")
|
@router.post(path="/login", response_model=Token)
|
||||||
async def login(
|
async def login(
|
||||||
session: sessionDep,
|
session: sessionDep,
|
||||||
credential: Annotated[OAuth2PasswordRequestForm, Depends()],
|
credential: Annotated[OAuth2PasswordRequestForm, Depends()],
|
||||||
|
response: Response
|
||||||
):
|
):
|
||||||
access_token = await AuthService(session).login(
|
result = await AuthService(session).login(
|
||||||
credential.username, credential.password
|
credential.username, credential.password
|
||||||
)
|
)
|
||||||
return access_token
|
response.set_cookie(
|
||||||
|
key="refresh_token",
|
||||||
|
value=result["refresh_token"],
|
||||||
|
httponly=True,
|
||||||
|
samesite='lax',
|
||||||
|
path=settings.api.v1.auth,
|
||||||
|
max_age=60 * 60 * 24 * 7
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@router.post(path="/refresh")
|
||||||
|
async def refresh(user: ActiveUser, response: Response):
|
||||||
|
print(response)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import secrets
|
||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone
|
||||||
|
|
||||||
import jwt
|
import jwt
|
||||||
@@ -34,6 +35,14 @@ class AuthManager:
|
|||||||
)
|
)
|
||||||
return encoded_jwt
|
return encoded_jwt
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_refresh_token(cls) -> str:
|
||||||
|
# random_bytes = os.urandom(32)
|
||||||
|
# data = settings.refresh_token.secret_key.encode() + random_bytes
|
||||||
|
# token_hash = bcrypt.hashpw(data, bcrypt.gensalt(rounds=12)).decode()
|
||||||
|
token_hash = secrets.token_urlsafe(32)
|
||||||
|
return token_hash
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def decode_access_token(cls, token: str) -> dict:
|
def decode_access_token(cls, token: str) -> dict:
|
||||||
return jwt.decode(
|
return jwt.decode(
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from typing import Any
|
|||||||
|
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
|
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
|
||||||
|
|
||||||
|
from src.repository.auth import AuthRepo
|
||||||
from src.repository.tasks import TasksRepo
|
from src.repository.tasks import TasksRepo
|
||||||
from src.repository.users import UsersRepo
|
from src.repository.users import UsersRepo
|
||||||
|
|
||||||
@@ -14,6 +15,7 @@ class DBManager:
|
|||||||
self.session: AsyncSession = self.session_factory()
|
self.session: AsyncSession = self.session_factory()
|
||||||
self.user = UsersRepo(self.session)
|
self.user = UsersRepo(self.session)
|
||||||
self.task = TasksRepo(self.session)
|
self.task = TasksRepo(self.session)
|
||||||
|
self.auth = AuthRepo(self.session)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
|
async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from typing import TYPE_CHECKING, Any, Protocol
|
|||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
from src.repository.auth import AuthRepo
|
||||||
from src.repository.tasks import TasksRepo
|
from src.repository.tasks import TasksRepo
|
||||||
from src.repository.users import UsersRepo
|
from src.repository.users import UsersRepo
|
||||||
|
|
||||||
@@ -15,6 +16,7 @@ class IUOWDB(Protocol):
|
|||||||
session: AsyncSession
|
session: AsyncSession
|
||||||
user: 'UsersRepo'
|
user: 'UsersRepo'
|
||||||
task: 'TasksRepo'
|
task: 'TasksRepo'
|
||||||
|
auth: 'AuthRepo'
|
||||||
|
|
||||||
async def __aenter__(self) -> "IUOWDB": ...
|
async def __aenter__(self) -> "IUOWDB": ...
|
||||||
|
|
||||||
|
|||||||
6
src/repository/auth.py
Normal file
6
src/repository/auth.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from src.models.tokens import RefreshTokensORM
|
||||||
|
from src.repository.base import BaseRepo
|
||||||
|
|
||||||
|
|
||||||
|
class AuthRepo(BaseRepo):
|
||||||
|
model: type[RefreshTokensORM] = RefreshTokensORM
|
||||||
@@ -4,6 +4,7 @@ from pydantic import BaseModel, ConfigDict, Field
|
|||||||
class Token(BaseModel):
|
class Token(BaseModel):
|
||||||
access_token: str
|
access_token: str
|
||||||
token_type: str
|
token_type: str
|
||||||
|
model_config = ConfigDict(extra='ignore')
|
||||||
|
|
||||||
|
|
||||||
class TokenData(BaseModel):
|
class TokenData(BaseModel):
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from fastapi import HTTPException
|
|||||||
|
|
||||||
from src.core.auth_manager import AuthManager
|
from src.core.auth_manager import AuthManager
|
||||||
from src.core.settings import settings
|
from src.core.settings import settings
|
||||||
from src.schemas.auth import Token, TokenData
|
from src.schemas.auth import TokenData
|
||||||
from src.schemas.users import User, UserAdd, UserRequestADD, UserWithHashedPass
|
from src.schemas.users import User, UserAdd, UserRequestADD, UserWithHashedPass
|
||||||
from src.services.base import BaseService
|
from src.services.base import BaseService
|
||||||
|
|
||||||
@@ -39,6 +39,7 @@ class AuthService(BaseService):
|
|||||||
access_token = AuthManager.create_access_token(
|
access_token = AuthManager.create_access_token(
|
||||||
user_token.model_dump()
|
user_token.model_dump()
|
||||||
)
|
)
|
||||||
return Token(
|
refresh_token = AuthManager.create_refresh_token()
|
||||||
access_token=access_token, token_type=settings.access_token.token_type
|
await self.session.auth.create_one({"token": refresh_token, "user_id": user.id})
|
||||||
)
|
await self.session.commit()
|
||||||
|
return {"access_token": access_token, "token_type": settings.access_token.token_type, "refresh_token": refresh_token}
|
||||||
Reference in New Issue
Block a user