base logic

This commit is contained in:
IluaAir
2025-07-06 11:58:45 +03:00
parent 817a799ef5
commit 4de11f4149
23 changed files with 149 additions and 17 deletions

39
poetry.lock generated
View File

@@ -101,6 +101,43 @@ files = [
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
] ]
[[package]]
name = "dnspython"
version = "2.7.0"
description = "DNS toolkit"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86"},
{file = "dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1"},
]
[package.extras]
dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "hypercorn (>=0.16.0)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "quart-trio (>=0.11.0)", "sphinx (>=7.2.0)", "sphinx-rtd-theme (>=2.0.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"]
dnssec = ["cryptography (>=43)"]
doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"]
doq = ["aioquic (>=1.0.0)"]
idna = ["idna (>=3.7)"]
trio = ["trio (>=0.23)"]
wmi = ["wmi (>=1.5.1)"]
[[package]]
name = "email-validator"
version = "2.2.0"
description = "A robust email address syntax and deliverability validation library."
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "email_validator-2.2.0-py3-none-any.whl", hash = "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631"},
{file = "email_validator-2.2.0.tar.gz", hash = "sha256:cb690f344c617a714f22e66ae771445a1ceb46821152df8e165c5f9a364582b7"},
]
[package.dependencies]
dnspython = ">=2.0.0"
idna = ">=2.0.0"
[[package]] [[package]]
name = "fastapi" name = "fastapi"
version = "0.115.14" version = "0.115.14"
@@ -721,4 +758,4 @@ standard = ["colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.6.3)
[metadata] [metadata]
lock-version = "2.1" lock-version = "2.1"
python-versions = ">=3.12" python-versions = ">=3.12"
content-hash = "e9bc371ef3ba3a59fce2dbc0416fbb5be92bbccf98f36bd661ed55318975f3a1" content-hash = "78991183ad2dfe443ab27c24820d79f492bb74ef261393364004ba457a42ba65"

View File

@@ -21,6 +21,7 @@ dependencies = [
"fastapi (>=0.115.14,<0.116.0)", "fastapi (>=0.115.14,<0.116.0)",
"pyjwt (>=2.10.1,<3.0.0)", "pyjwt (>=2.10.1,<3.0.0)",
"passlib (>=1.7.4,<2.0.0)", "passlib (>=1.7.4,<2.0.0)",
"email-validator (>=2.2.0,<3.0.0)",
] ]

View File

@@ -1,8 +1,9 @@
from fastapi import APIRouter from fastapi import APIRouter
from src.api.users import router as users_router
from src.api.tasks import router as tasks_router
router = APIRouter() from src.api.v1 import router as v1_router
from src.core.settings import settings
router = APIRouter(prefix=settings.api.prefix)
router.include_router(router=v1_router)
router.include_router(router=users_router)
router.include_router(router=tasks_router)

View File

@@ -3,7 +3,7 @@ from typing import Annotated, AsyncGenerator
from fastapi import Depends from fastapi import Depends
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from src.db.database import async_session_maker from src.core.database import async_session_maker
async def get_db() -> AsyncGenerator[AsyncSession, None]: async def get_db() -> AsyncGenerator[AsyncSession, None]:
@@ -11,6 +11,6 @@ async def get_db() -> AsyncGenerator[AsyncSession, None]:
yield db yield db
DBDep = Annotated[AsyncSession, Depends(get_db)] sessionDep = Annotated[AsyncSession, Depends(get_db)]

View File

@@ -1,3 +0,0 @@
from fastapi import APIRouter
router = APIRouter(prefix="/users", tags=["Users"])

11
src/api/v1/__init__.py Normal file
View File

@@ -0,0 +1,11 @@
from fastapi import APIRouter
from src.api.v1.auth import router as auth_router
from src.api.v1.users import router as users_router
from src.api.v1.tasks import router as tasks_router
from src.core.settings import settings
router = APIRouter(prefix=settings.api.v1.prefix)
router.include_router(router=auth_router)
router.include_router(router=users_router)
router.include_router(router=tasks_router)

13
src/api/v1/auth.py Normal file
View File

@@ -0,0 +1,13 @@
from fastapi import APIRouter
from src.api.dependacies.db_dep import sessionDep
from src.schemas.users import UserCreate
from src.core.settings import settings
from src.services.auth import AuthService
router = APIRouter(prefix=settings.api.v1.auth, tags=['Auth'])
@router.post(path='/signup')
async def registration(session: sessionDep, credential: UserCreate):
await AuthService(session).registration(credential)

5
src/api/v1/users.py Normal file
View File

@@ -0,0 +1,5 @@
from fastapi import APIRouter
from src.core.settings import settings
router = APIRouter(prefix=settings.api.v1.users, tags=["Users"])

View File

@@ -4,7 +4,7 @@ from sqlalchemy import TIMESTAMP, func
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from src.settings import settings from src.core.settings import settings
engine = create_async_engine(settings.db.url, echo=True) engine = create_async_engine(settings.db.url, echo=True)

View File

@@ -7,6 +7,17 @@ BASE_DIR = Path(__file__).parent
DB_PATH = BASE_DIR / "db/taskncoffee.db" DB_PATH = BASE_DIR / "db/taskncoffee.db"
class ApiV1Prefix(BaseModel):
prefix: str = "/v1"
auth: str = "/auth"
users: str = "/users"
class ApiPrefix(BaseModel):
prefix: str = "/api"
v1: ApiV1Prefix = ApiV1Prefix()
class DbSettings(BaseModel): class DbSettings(BaseModel):
url: str = f"sqlite+aiosqlite:///{DB_PATH}" url: str = f"sqlite+aiosqlite:///{DB_PATH}"
@@ -22,7 +33,7 @@ class AccessToken(BaseSettings):
class Settings(BaseSettings): class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file='.env', env_file_encoding='utf-8') api: ApiPrefix = ApiPrefix()
db: DbSettings = DbSettings() db: DbSettings = DbSettings()
access_token: AccessToken = AccessToken() access_token: AccessToken = AccessToken()

View File

@@ -11,4 +11,4 @@ app = FastAPI()
app.include_router(router=router) app.include_router(router=router)
if __name__ == "__main__": if __name__ == "__main__":
uvicorn.run("src.main:app", port=5000, log_level="info", reload=True) uvicorn.run("src.main:app", port=8000, log_level="info", reload=True)

View File

@@ -4,7 +4,7 @@ from typing import Optional, TYPE_CHECKING
from sqlalchemy import ForeignKey, Text, Date, Enum, String from sqlalchemy import ForeignKey, Text, Date, Enum, String
from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.orm import Mapped, mapped_column, relationship
from src.db.database import Base from src.core.database import Base
if TYPE_CHECKING: if TYPE_CHECKING:
from src.models.users import UsersORM from src.models.users import UsersORM

View File

@@ -1,9 +1,9 @@
from typing import Optional, TYPE_CHECKING from typing import Optional, TYPE_CHECKING
from sqlalchemy import String, BigInteger, Integer, Boolean, VARCHAR from sqlalchemy import String, BigInteger, Integer, Boolean
from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.orm import Mapped, mapped_column, relationship
from src.db.database import Base from src.core.database import Base
if TYPE_CHECKING: if TYPE_CHECKING:
from src.models.tasks import TasksORM from src.models.tasks import TasksORM

View File

View File

@@ -0,0 +1,15 @@
from pydantic import BaseModel, EmailStr
class UserRead(BaseModel):
username: str
email: EmailStr | None
is_active: bool
is_superuser: bool
class UserCreate(BaseModel):
username: str
email: EmailStr | None = None
password: str

0
src/services/__init__.py Normal file
View File

11
src/services/auth.py Normal file
View File

@@ -0,0 +1,11 @@
from src.schemas.users import UserCreate
from src.services.base import BaseService
class AuthService(BaseService):
async def registration(self, data: UserCreate):
...

9
src/services/base.py Normal file
View File

@@ -0,0 +1,9 @@
from src.utils.db_manager import DBManager
class BaseService:
session: DBManager | None
def __init__(self, session: DBManager):
self.session = session

View File

@@ -0,0 +1,9 @@
from passlib.context import CryptContext
class AuthManger:
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
@classmethod
def verify_password(cls, plain_password, hashed_password):
return cls.pwd_context.verify(plain_password, hashed_password)

12
src/utils/db_manager.py Normal file
View File

@@ -0,0 +1,12 @@
class DBManager:
def __init__(self, session_factory):
self.session_factory = session_factory
async def __aenter__(self):
self.session = self.session_factory()
async def __aexit__(self, exc_type, exc_val, exc_tb):
await self.session.rollback()
await self.session.close()