from fastapi import APIRouter, Depends, Request from fastapi.responses import HTMLResponse, RedirectResponse from sqlalchemy import or_ from sqlalchemy.orm import Session from web.auth.password import hash_password, verify_password from web.auth.session import get_current_user from web.config import settings from web.database import get_db from web.models.user import User from web.templates_env import templates router = APIRouter() def _render(request: Request, template: str, ctx: dict) -> HTMLResponse: ctx["request"] = request ctx.setdefault("jivosite_widget_id", settings.JIVOSITE_WIDGET_ID) return templates.TemplateResponse(ctx.pop("request"), template, ctx) @router.get("/profile") async def profile_view(request: Request, db: Session = Depends(get_db)): try: user = get_current_user(request, db) except Exception: return RedirectResponse("/login", 303) return _render(request, "profile_view.html", {"user": user}) @router.get("/profile/edit") async def profile_edit_get(request: Request, db: Session = Depends(get_db)): try: user = get_current_user(request, db) except Exception: return RedirectResponse("/login", 303) return _render(request, "profile_edit.html", {"user": user}) @router.post("/profile/edit") async def profile_edit_post(request: Request, db: Session = Depends(get_db)): try: user = get_current_user(request, db) except Exception: return RedirectResponse("/login", 303) form = await request.form() data = {k: str(v).strip() for k, v in form.items()} errors = [] if not data.get("first_name"): errors.append("Имя обязательно") if not data.get("last_name"): errors.append("Фамилия обязательна") if not data.get("phone"): errors.append("Телефон обязателен") if not errors: dup = db.query(User).filter( User.phone == data["phone"], User.id != user.id ).first() if dup: errors.append("Пользователь с таким телефоном уже существует") if errors: return _render(request, "profile_edit.html", {"user": user, "errors": errors, "form": data}) user.first_name = data["first_name"] user.last_name = data["last_name"] user.phone = data["phone"] db.commit() return _render(request, "profile_edit.html", { "user": user, "success": "Профиль обновлён", }) @router.get("/profile/change-password") async def change_pw_get(request: Request, db: Session = Depends(get_db)): try: user = get_current_user(request, db) except Exception: return RedirectResponse("/login", 303) return _render(request, "profile_change_password.html", {"user": user}) @router.post("/profile/change-password") async def change_pw_post(request: Request, db: Session = Depends(get_db)): try: user = get_current_user(request, db) except Exception: return RedirectResponse("/login", 303) form = await request.form() current = str(form.get("current_password", "")) new_pw = str(form.get("password", "")) confirm = str(form.get("password_confirm", "")) errors = [] if not user.password_hash or not verify_password(current, user.password_hash): errors.append("Неверный текущий пароль") if len(new_pw) < 8: errors.append("Новый пароль должен содержать минимум 8 символов") if new_pw != confirm: errors.append("Пароли не совпадают") if errors: return _render(request, "profile_change_password.html", {"user": user, "errors": errors}) user.password_hash = hash_password(new_pw) db.commit() return _render(request, "profile_change_password.html", { "user": user, "success": "Пароль изменён", }) @router.get("/profile/delete") async def delete_get(request: Request, db: Session = Depends(get_db)): try: user = get_current_user(request, db) except Exception: return RedirectResponse("/login", 303) return _render(request, "profile_delete.html", {"user": user}) @router.post("/profile/delete") async def delete_post(request: Request, db: Session = Depends(get_db)): try: user = get_current_user(request, db) except Exception: return RedirectResponse("/login", 303) form = await request.form() password = str(form.get("password", "")) if not user.password_hash or not verify_password(password, user.password_hash): return _render(request, "profile_delete.html", { "user": user, "errors": ["Неверный пароль"], }) db.delete(user) db.commit() request.session.clear() return RedirectResponse("/login", 303)