Add user settings page and PWA install support
- Add profile update, password change, and account deletion endpoints - Create Settings page with profile editing, password change, and danger zone - Add Settings link to user dropdown menu in Layout - Add /settings route to App.tsx - Add API functions for profile management - Create PWA manifest.json and add meta tags to index.html
This commit is contained in:
@@ -7,6 +7,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from app.core.database import get_db
|
||||
from app.core.security import hash_password, verify_password, create_access_token, get_current_user
|
||||
from app.models.user import User
|
||||
from pydantic import BaseModel, EmailStr
|
||||
from app.schemas.auth import RegisterRequest, LoginRequest, TokenResponse, UserResponse
|
||||
from app.services.spotify import get_spotify_auth_url, exchange_spotify_code, get_spotify_user
|
||||
|
||||
@@ -29,6 +30,42 @@ async def register(data: RegisterRequest, db: AsyncSession = Depends(get_db)):
|
||||
return TokenResponse(access_token=create_access_token(user.id))
|
||||
|
||||
|
||||
class UpdateProfileRequest(BaseModel):
|
||||
name: str | None = None
|
||||
email: EmailStr | None = None
|
||||
|
||||
|
||||
class ChangePasswordRequest(BaseModel):
|
||||
current_password: str
|
||||
new_password: str
|
||||
|
||||
|
||||
@router.put("/me")
|
||||
async def update_profile(data: UpdateProfileRequest, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db)):
|
||||
if data.name:
|
||||
user.name = data.name
|
||||
if data.email and data.email != user.email:
|
||||
existing = await db.execute(select(User).where(User.email == data.email))
|
||||
if existing.scalar_one_or_none():
|
||||
raise HTTPException(status_code=400, detail="Email already in use")
|
||||
user.email = data.email
|
||||
return UserResponse(id=user.id, email=user.email, name=user.name, is_pro=user.is_pro, spotify_connected=user.spotify_id is not None)
|
||||
|
||||
|
||||
@router.post("/change-password")
|
||||
async def change_password(data: ChangePasswordRequest, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db)):
|
||||
if not user.hashed_password or not verify_password(data.current_password, user.hashed_password):
|
||||
raise HTTPException(status_code=400, detail="Current password is incorrect")
|
||||
user.hashed_password = hash_password(data.new_password)
|
||||
return {"ok": True}
|
||||
|
||||
|
||||
@router.delete("/me")
|
||||
async def delete_account(user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db)):
|
||||
await db.delete(user)
|
||||
return {"ok": True}
|
||||
|
||||
|
||||
@router.post("/login", response_model=TokenResponse)
|
||||
async def login(data: LoginRequest, db: AsyncSession = Depends(get_db)):
|
||||
result = await db.execute(select(User).where(User.email == data.email))
|
||||
|
||||
Reference in New Issue
Block a user