Загрузить файлы в «app/routers»
This commit is contained in:
BIN
app/routers/__init__.py
Normal file
BIN
app/routers/__init__.py
Normal file
Binary file not shown.
97
app/routers/api.py
Normal file
97
app/routers/api.py
Normal file
@@ -0,0 +1,97 @@
|
||||
import json
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, status
|
||||
from sqlalchemy.orm import Session as DbSession
|
||||
|
||||
from app.auth import verify_api_key
|
||||
from app.database import get_db
|
||||
from app.models import ExternalData, Session, User
|
||||
from app.schemas import ExternalDataCreate, ExternalDataPublic, SessionPublic, UserPublic
|
||||
|
||||
router = APIRouter(prefix="/api/v1", tags=["external-api"])
|
||||
|
||||
|
||||
@router.get("/users/{user_id}", response_model=UserPublic)
|
||||
def get_user(
|
||||
user_id: int,
|
||||
_: None = Depends(verify_api_key),
|
||||
db: DbSession = Depends(get_db),
|
||||
):
|
||||
user = db.query(User).filter(User.id == user_id).first()
|
||||
if not user:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
|
||||
return user
|
||||
|
||||
|
||||
@router.get("/users/by-email/{email}", response_model=UserPublic)
|
||||
def get_user_by_email(
|
||||
email: str,
|
||||
_: None = Depends(verify_api_key),
|
||||
db: DbSession = Depends(get_db),
|
||||
):
|
||||
user = db.query(User).filter(User.email == email.strip().lower()).first()
|
||||
if not user:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
|
||||
return user
|
||||
|
||||
|
||||
@router.get("/users/{user_id}/sessions", response_model=list[SessionPublic])
|
||||
def get_user_sessions(
|
||||
user_id: int,
|
||||
active_only: bool = True,
|
||||
_: None = Depends(verify_api_key),
|
||||
db: DbSession = Depends(get_db),
|
||||
):
|
||||
user = db.query(User).filter(User.id == user_id).first()
|
||||
if not user:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
|
||||
query = db.query(Session).filter(Session.user_id == user_id)
|
||||
if active_only:
|
||||
query = query.filter(Session.is_active.is_(True))
|
||||
return query.order_by(Session.created_at.desc()).all()
|
||||
|
||||
|
||||
@router.post("/users/{user_id}/data", response_model=ExternalDataPublic, status_code=status.HTTP_201_CREATED)
|
||||
def write_external_data(
|
||||
user_id: int,
|
||||
body: ExternalDataCreate,
|
||||
_: None = Depends(verify_api_key),
|
||||
db: DbSession = Depends(get_db),
|
||||
):
|
||||
user = db.query(User).filter(User.id == user_id).first()
|
||||
if not user:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
|
||||
|
||||
payload_str = body.payload if isinstance(body.payload, str) else json.dumps(body.payload, ensure_ascii=False)
|
||||
|
||||
record = ExternalData(user_id=user_id, source=body.source, payload=payload_str)
|
||||
db.add(record)
|
||||
|
||||
if body.points_delta:
|
||||
user.points = max(0, user.points + body.points_delta)
|
||||
if body.rating_delta:
|
||||
user.rating = max(0.0, user.rating + body.rating_delta)
|
||||
|
||||
db.commit()
|
||||
db.refresh(record)
|
||||
return record
|
||||
|
||||
|
||||
@router.get("/users/{user_id}/data", response_model=list[ExternalDataPublic])
|
||||
def get_external_data(
|
||||
user_id: int,
|
||||
limit: int = 50,
|
||||
_: None = Depends(verify_api_key),
|
||||
db: DbSession = Depends(get_db),
|
||||
):
|
||||
user = db.query(User).filter(User.id == user_id).first()
|
||||
if not user:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
|
||||
limit = min(max(limit, 1), 100)
|
||||
return (
|
||||
db.query(ExternalData)
|
||||
.filter(ExternalData.user_id == user_id)
|
||||
.order_by(ExternalData.created_at.desc())
|
||||
.limit(limit)
|
||||
.all()
|
||||
)
|
||||
139
app/routers/web.py
Normal file
139
app/routers/web.py
Normal file
@@ -0,0 +1,139 @@
|
||||
from fastapi import APIRouter, Depends, Form, HTTPException, Request, status
|
||||
from fastapi.responses import HTMLResponse, RedirectResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from sqlalchemy.orm import Session as DbSession
|
||||
|
||||
from app.auth import (
|
||||
SESSION_COOKIE,
|
||||
create_user_session,
|
||||
get_current_user,
|
||||
get_current_user_optional,
|
||||
hash_password,
|
||||
verify_password,
|
||||
)
|
||||
from app.database import get_db
|
||||
from app.models import Session, User
|
||||
|
||||
router = APIRouter(tags=["web"])
|
||||
templates = Jinja2Templates(directory="templates")
|
||||
|
||||
|
||||
@router.get("/", response_class=HTMLResponse)
|
||||
def index(request: Request, user: User | None = Depends(get_current_user_optional)):
|
||||
if user:
|
||||
return RedirectResponse("/cabinet", status_code=status.HTTP_302_FOUND)
|
||||
return RedirectResponse("/login", status_code=status.HTTP_302_FOUND)
|
||||
|
||||
|
||||
@router.get("/register", response_class=HTMLResponse)
|
||||
def register_page(request: Request, user: User | None = Depends(get_current_user_optional)):
|
||||
if user:
|
||||
return RedirectResponse("/cabinet", status_code=status.HTTP_302_FOUND)
|
||||
return templates.TemplateResponse(request, "register.html", {"error": None})
|
||||
|
||||
|
||||
@router.post("/register")
|
||||
def register(
|
||||
request: Request,
|
||||
email: str = Form(...),
|
||||
password: str = Form(...),
|
||||
db: DbSession = Depends(get_db),
|
||||
):
|
||||
email = email.strip().lower()
|
||||
if len(password) < 6:
|
||||
return templates.TemplateResponse(
|
||||
request,
|
||||
"register.html",
|
||||
{"error": "Пароль должен быть не менее 6 символов"},
|
||||
status_code=400,
|
||||
)
|
||||
existing = db.query(User).filter(User.email == email).first()
|
||||
if existing:
|
||||
return templates.TemplateResponse(
|
||||
request,
|
||||
"register.html",
|
||||
{"error": "Пользователь с такой почтой уже существует"},
|
||||
status_code=400,
|
||||
)
|
||||
user = User(email=email, password_hash=hash_password(password))
|
||||
db.add(user)
|
||||
db.commit()
|
||||
db.refresh(user)
|
||||
session = create_user_session(db, user)
|
||||
response = RedirectResponse("/cabinet", status_code=status.HTTP_302_FOUND)
|
||||
response.set_cookie(
|
||||
key=SESSION_COOKIE,
|
||||
value=session.token,
|
||||
httponly=True,
|
||||
samesite="lax",
|
||||
max_age=86400,
|
||||
)
|
||||
return response
|
||||
|
||||
|
||||
@router.get("/login", response_class=HTMLResponse)
|
||||
def login_page(request: Request, user: User | None = Depends(get_current_user_optional)):
|
||||
if user:
|
||||
return RedirectResponse("/cabinet", status_code=status.HTTP_302_FOUND)
|
||||
return templates.TemplateResponse(request, "login.html", {"error": None})
|
||||
|
||||
|
||||
@router.post("/login")
|
||||
def login(
|
||||
request: Request,
|
||||
email: str = Form(...),
|
||||
password: str = Form(...),
|
||||
db: DbSession = Depends(get_db),
|
||||
):
|
||||
email = email.strip().lower()
|
||||
user = db.query(User).filter(User.email == email).first()
|
||||
if not user or not verify_password(password, user.password_hash):
|
||||
return templates.TemplateResponse(
|
||||
request,
|
||||
"login.html",
|
||||
{"error": "Неверная почта или пароль"},
|
||||
status_code=400,
|
||||
)
|
||||
session = create_user_session(db, user)
|
||||
response = RedirectResponse("/cabinet", status_code=status.HTTP_302_FOUND)
|
||||
response.set_cookie(
|
||||
key=SESSION_COOKIE,
|
||||
value=session.token,
|
||||
httponly=True,
|
||||
samesite="lax",
|
||||
max_age=86400,
|
||||
)
|
||||
return response
|
||||
|
||||
|
||||
@router.post("/logout")
|
||||
def logout(request: Request, db: DbSession = Depends(get_db)):
|
||||
token = request.cookies.get(SESSION_COOKIE)
|
||||
if token:
|
||||
session = db.query(Session).filter(Session.token == token).first()
|
||||
if session:
|
||||
session.is_active = False
|
||||
db.commit()
|
||||
response = RedirectResponse("/login", status_code=status.HTTP_302_FOUND)
|
||||
response.delete_cookie(SESSION_COOKIE)
|
||||
return response
|
||||
|
||||
|
||||
@router.get("/cabinet", response_class=HTMLResponse)
|
||||
def cabinet(request: Request, user: User = Depends(get_current_user), db: DbSession = Depends(get_db)):
|
||||
sessions = (
|
||||
db.query(Session)
|
||||
.filter(Session.user_id == user.id, Session.is_active.is_(True))
|
||||
.order_by(Session.created_at.desc())
|
||||
.all()
|
||||
)
|
||||
external_data = list(reversed(user.external_data[-10:])) if user.external_data else []
|
||||
return templates.TemplateResponse(
|
||||
request,
|
||||
"cabinet.html",
|
||||
{
|
||||
"user": user,
|
||||
"sessions": sessions,
|
||||
"external_data": external_data,
|
||||
},
|
||||
)
|
||||
Reference in New Issue
Block a user