summaryrefslogtreecommitdiff
path: root/app/routes
diff options
context:
space:
mode:
Diffstat (limited to 'app/routes')
-rw-r--r--app/routes/__init__.py19
-rw-r--r--app/routes/auth/__init__.py0
-rw-r--r--app/routes/auth/auth.py (renamed from app/routes/auth.py)0
-rw-r--r--app/routes/auth/logout.py35
-rw-r--r--app/routes/auth/register.py (renamed from app/routes/register.py)0
-rw-r--r--app/routes/me.py51
-rw-r--r--app/routes/users/__init__.py0
-rw-r--r--app/routes/users/changeusername.py40
-rw-r--r--app/routes/users/me.py17
-rw-r--r--app/routes/users/security.py0
-rw-r--r--app/routes/users/user.py (renamed from app/routes/user.py)0
11 files changed, 104 insertions, 58 deletions
diff --git a/app/routes/__init__.py b/app/routes/__init__.py
index a57869a..65d9c36 100644
--- a/app/routes/__init__.py
+++ b/app/routes/__init__.py
@@ -1,13 +1,18 @@
from fastapi import APIRouter
-from .auth import router as auth_router
-from .me import router as me_router
-from .register import router as register_router
-from .user import router as user_router
+from app.routes.auth.auth import router as auth_router
+from app.routes.auth.logout import router as logout_router
+from app.routes.auth.register import router as register_router
+from app.routes.users.changeusername import router as changeusername_router
+from app.routes.users.me import router as me_router
+from app.routes.users.user import router as user_router
router = APIRouter()
-router.include_router(register_router, prefix="/auth")
-router.include_router(auth_router, prefix="/auth")
-router.include_router(user_router)
+router.include_router(changeusername_router)
router.include_router(me_router)
+router.include_router(user_router)
+
+router.include_router(auth_router, prefix="/auth")
+router.include_router(register_router, prefix="/auth")
+router.include_router(logout_router, prefix="/auth")
diff --git a/app/routes/auth/__init__.py b/app/routes/auth/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/routes/auth/__init__.py
diff --git a/app/routes/auth.py b/app/routes/auth/auth.py
index 6e0d410..6e0d410 100644
--- a/app/routes/auth.py
+++ b/app/routes/auth/auth.py
diff --git a/app/routes/auth/logout.py b/app/routes/auth/logout.py
new file mode 100644
index 0000000..a55ea9e
--- /dev/null
+++ b/app/routes/auth/logout.py
@@ -0,0 +1,35 @@
+from fastapi import APIRouter, Depends, Response
+from sqlalchemy.ext.asyncio import AsyncSession
+
+from app.auth.dependencies import get_current_user
+from app.models.user import User
+from app.utils.db import get_async_session
+from app.utils.logger_cfg import logger
+
+router = APIRouter(tags=["auth"])
+
+
+COOKIE_KWARGS = {
+ "httponly": True,
+ "secure": False,
+ "samesite": "lax",
+ "path": "/",
+}
+
+
+@router.post("/logout")
+async def logout(
+ response: Response,
+ session: AsyncSession = Depends(get_async_session),
+ user: User = Depends(get_current_user),
+):
+ response.delete_cookie("access_token", **COOKIE_KWARGS)
+ response.delete_cookie("refresh_token", **COOKIE_KWARGS)
+
+ user.token_version += 1
+ session.add(user)
+ await session.commit()
+
+ logger.info("User logged out everywhere | user_id={}", user.id)
+
+ return {"message": "Logged out successfully"}
diff --git a/app/routes/register.py b/app/routes/auth/register.py
index f0b36ed..f0b36ed 100644
--- a/app/routes/register.py
+++ b/app/routes/auth/register.py
diff --git a/app/routes/me.py b/app/routes/me.py
deleted file mode 100644
index 6d28a80..0000000
--- a/app/routes/me.py
+++ /dev/null
@@ -1,51 +0,0 @@
-from fastapi import APIRouter, Depends, Request
-from sqlalchemy.ext.asyncio import AsyncSession
-
-from app.auth.jwt import decode_token
-from app.models.user import User
-from app.utils.db import get_async_session
-
-router = APIRouter(tags=["auth"])
-
-
-async def get_current_user_from_cookie(
- request: Request,
- session: AsyncSession = Depends(get_async_session),
-) -> dict:
- token = request.cookies.get("access_token")
- if not token:
- return {"authenticated": False, "user": None}
-
- try:
- payload = decode_token(token)
- sub = payload.get("sub")
- if sub is None:
- return {"authenticated": False, "user": None}
- user_id = int(sub)
- except ValueError, TypeError:
- return {"authenticated": False, "user": None}
-
- user = await User.get_user_by_id(user_id, session=session)
- if not user or user.token_version != payload.get("token_version"):
- return {"authenticated": False, "user": None}
-
- return {
- "authenticated": True,
- "user": {
- "id": user.id,
- "username": user.username,
- "password": user.has_password,
- "google_id": user.google_id,
- "email": user.email,
- "premium": user.premium,
- "is_banned": user.is_banned,
- "is_moderator": user.is_moderator,
- },
- }
-
-
-@router.get("/me")
-async def read_current_user(
- user_info: dict = Depends(get_current_user_from_cookie),
-):
- return user_info
diff --git a/app/routes/users/__init__.py b/app/routes/users/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/routes/users/__init__.py
diff --git a/app/routes/users/changeusername.py b/app/routes/users/changeusername.py
new file mode 100644
index 0000000..66ba8da
--- /dev/null
+++ b/app/routes/users/changeusername.py
@@ -0,0 +1,40 @@
+from fastapi import APIRouter, Depends, HTTPException
+from pydantic import BaseModel
+from sqlalchemy.ext.asyncio import AsyncSession
+
+from app.auth.dependencies import get_current_user
+from app.models.user import User
+from app.utils.db import get_async_session
+
+router = APIRouter()
+
+
+class ChangeUsernameRequest(BaseModel):
+ username: str
+
+
+@router.patch("/users/change-username")
+async def change_username(
+ data: ChangeUsernameRequest,
+ user_info: dict = Depends(get_current_user),
+ session: AsyncSession = Depends(get_async_session),
+):
+ if not user_info["authenticated"]:
+ raise HTTPException(status_code=401, detail="Not authenticated")
+
+ user = user_info["user"]
+
+ if len(data.username) < 3:
+ raise HTTPException(status_code=400, detail="Username too short")
+
+ db_user = await session.get(User, user["id"])
+
+ if not db_user:
+ raise HTTPException(status_code=404, detail="User not found")
+
+ db_user.username = data.username
+
+ await session.commit()
+ await session.refresh(db_user)
+
+ return {"success": True, "username": db_user.username}
diff --git a/app/routes/users/me.py b/app/routes/users/me.py
new file mode 100644
index 0000000..a54fbfe
--- /dev/null
+++ b/app/routes/users/me.py
@@ -0,0 +1,17 @@
+from fastapi import APIRouter, Depends
+
+from app.auth.dependencies import get_optional_user
+from app.models.user import User
+from app.schemas.user import MeResponse, UserRead
+
+router = APIRouter(tags=["auth"])
+
+
+@router.get("/me", response_model=MeResponse)
+async def me(
+ user: User | None = Depends(get_optional_user),
+):
+ return MeResponse(
+ authenticated=user is not None,
+ user=UserRead.model_validate(user) if user else None,
+ )
diff --git a/app/routes/users/security.py b/app/routes/users/security.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/routes/users/security.py
diff --git a/app/routes/user.py b/app/routes/users/user.py
index 1eb096d..1eb096d 100644
--- a/app/routes/user.py
+++ b/app/routes/users/user.py