summaryrefslogtreecommitdiff
path: root/app/routes/users/user.py
blob: 034233e6ef7f711888166095b98eace3755142be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
from fastapi import APIRouter, Body, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession

from app.auth.dependencies import get_current_user
from app.models.user import User
from app.schemas.profile import DescriptionUpdate
from app.schemas.user import ChangeEmail, ChangePassword, SetPassword, UserRead
from app.utils.db import get_async_session
from app.utils.hash_cfg import hash_password, verify_password

router = APIRouter(prefix="/users", tags=["users"])


@router.get("/{username}", response_model=UserRead)
async def get_user(
    username: str,
    session: AsyncSession = Depends(get_async_session),
):
    user = await User.get_user_by_username(username, session=session)

    if not user:
        raise HTTPException(status_code=404, detail="User not found")

    return UserRead.model_validate(user)


@router.patch("/description")
async def update_description(
    payload: DescriptionUpdate,
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_async_session),
):
    profile = user.profile

    if not profile:
        raise HTTPException(status_code=404, detail="Profile not found")

    profile.description = payload.description

    session.add(profile)
    await session.commit()
    await session.refresh(profile)

    return {"description": profile.description}


@router.patch("/email")
async def change_email(
    data: ChangeEmail = Body(...),
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_async_session),
):
    user.email = data.email

    session.add(user)
    await session.commit()
    await session.refresh(user)

    return {"email": user.email}


@router.patch("/password")
async def change_password(
    data: ChangePassword = Body(...),
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_async_session),
):
    if not user.password:
        raise HTTPException(status_code=400, detail="User has no password set")

    if not verify_password(data.current_password, user.password):
        raise HTTPException(
            status_code=400,
            detail="Invalid current password",
        )

    if verify_password(data.new_password, user.password):
        raise HTTPException(
            status_code=400,
            detail="New password must be different from current password",
        )

    hashed = hash_password(data.new_password)

    user.password = hashed

    session.add(user)
    await session.commit()
    await session.refresh(user)

    return {
        "success": True,
        "message": "Password updated successfully",
    }


@router.post("/password/set")
async def set_password(
    data: SetPassword,
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_async_session),
):
    if user.password:
        raise HTTPException(status_code=400, detail="Password already set")

    if data.new_password != data.repeat_password:
        raise HTTPException(status_code=400, detail="Passwords do not match")

    user.password = hash_password(data.new_password)

    session.add(user)
    await session.commit()
    await session.refresh(user)

    return {"success": True}