users.py 5.99 KB
Newer Older
Timothy J. Baek's avatar
Timothy J. Baek committed
1
from fastapi import Response, Request
Timothy J. Baek's avatar
Timothy J. Baek committed
2
3
4
5
6
7
8
9
from fastapi import Depends, FastAPI, HTTPException, status
from datetime import datetime, timedelta
from typing import List, Union, Optional

from fastapi import APIRouter
from pydantic import BaseModel
import time
import uuid
10
import logging
Timothy J. Baek's avatar
Timothy J. Baek committed
11

12
13
14
15
16
17
18
from apps.webui.models.users import (
    UserModel,
    UserUpdateForm,
    UserRoleUpdateForm,
    UserSettings,
    Users,
)
19
20
from apps.webui.models.auths import Auths
from apps.webui.models.chats import Chats
Timothy J. Baek's avatar
Timothy J. Baek committed
21

22
from utils.utils import get_verified_user, get_password_hash, get_admin_user
Timothy J. Baek's avatar
Timothy J. Baek committed
23
24
from constants import ERROR_MESSAGES

25
from config import SRC_LOG_LEVELS
Timothy J. Baek's avatar
Timothy J. Baek committed
26

27
28
29
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])

Timothy J. Baek's avatar
Timothy J. Baek committed
30
31
32
33
34
35
36
37
router = APIRouter()

############################
# GetUsers
############################


@router.get("/", response_model=List[UserModel])
38
async def get_users(skip: int = 0, limit: int = 50, user=Depends(get_admin_user)):
39
    return Users.get_users(skip, limit)
Timothy J. Baek's avatar
Timothy J. Baek committed
40
41


Timothy J. Baek's avatar
Timothy J. Baek committed
42
43
44
45
46
47
48
############################
# User Permissions
############################


@router.get("/permissions/user")
async def get_user_permissions(request: Request, user=Depends(get_admin_user)):
49
    return request.app.state.config.USER_PERMISSIONS
Timothy J. Baek's avatar
Timothy J. Baek committed
50
51
52
53
54
55


@router.post("/permissions/user")
async def update_user_permissions(
    request: Request, form_data: dict, user=Depends(get_admin_user)
):
56
57
    request.app.state.config.USER_PERMISSIONS = form_data
    return request.app.state.config.USER_PERMISSIONS
Timothy J. Baek's avatar
Timothy J. Baek committed
58
59


Timothy J. Baek's avatar
Timothy J. Baek committed
60
61
62
63
64
65
############################
# UpdateUserRole
############################


@router.post("/update/role", response_model=Optional[UserModel])
Timothy J. Baek's avatar
Timothy J. Baek committed
66
67
async def update_user_role(form_data: UserRoleUpdateForm, user=Depends(get_admin_user)):

68
    if user.id != form_data.id and form_data.id != Users.get_first_user().id:
Timothy J. Baek's avatar
Timothy J. Baek committed
69
        return Users.update_user_role_by_id(form_data.id, form_data.role)
70
71
72
73
74

    raise HTTPException(
        status_code=status.HTTP_403_FORBIDDEN,
        detail=ERROR_MESSAGES.ACTION_PROHIBITED,
    )
Timothy J. Baek's avatar
Timothy J. Baek committed
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
############################
# GetUserSettingsBySessionUser
############################


@router.get("/user/settings", response_model=Optional[UserSettings])
async def get_user_settings_by_session_user(user=Depends(get_verified_user)):
    user = Users.get_user_by_id(user.id)
    if user:
        return user.settings
    else:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=ERROR_MESSAGES.USER_NOT_FOUND,
        )


############################
# UpdateUserSettingsBySessionUser
############################


@router.post("/user/settings/update", response_model=UserSettings)
async def update_user_settings_by_session_user(
    form_data: UserSettings, user=Depends(get_verified_user)
):
    user = Users.update_user_by_id(user.id, {"settings": form_data.model_dump()})
    if user:
        return user.settings
    else:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=ERROR_MESSAGES.USER_NOT_FOUND,
        )


113
114
115
116
117
118
119
120
121
122
123
124
125
############################
# GetUserById
############################


class UserResponse(BaseModel):
    name: str
    profile_image_url: str


@router.get("/{user_id}", response_model=UserResponse)
async def get_user_by_id(user_id: str, user=Depends(get_verified_user)):

126
127
    # Check if user_id is a shared chat
    # If it is, get the user_id from the chat
Timothy J. Baek's avatar
Timothy J. Baek committed
128
129
130
131
132
133
134
135
136
137
138
    if user_id.startswith("shared-"):
        chat_id = user_id.replace("shared-", "")
        chat = Chats.get_chat_by_id(chat_id)
        if chat:
            user_id = chat.user_id
        else:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=ERROR_MESSAGES.USER_NOT_FOUND,
            )

139
140
141
142
143
144
145
146
147
148
149
    user = Users.get_user_by_id(user_id)

    if user:
        return UserResponse(name=user.name, profile_image_url=user.profile_image_url)
    else:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=ERROR_MESSAGES.USER_NOT_FOUND,
        )


Timothy J. Baek's avatar
Timothy J. Baek committed
150
############################
Timothy J. Baek's avatar
Timothy J. Baek committed
151
# UpdateUserById
Timothy J. Baek's avatar
Timothy J. Baek committed
152
153
154
############################


Timothy J. Baek's avatar
Timothy J. Baek committed
155
156
@router.post("/{user_id}/update", response_model=Optional[UserModel])
async def update_user_by_id(
157
    user_id: str, form_data: UserUpdateForm, session_user=Depends(get_admin_user)
Timothy J. Baek's avatar
Timothy J. Baek committed
158
159
160
161
):
    user = Users.get_user_by_id(user_id)

    if user:
Timothy J. Baek's avatar
Timothy J. Baek committed
162
163
        if form_data.email.lower() != user.email:
            email_user = Users.get_user_by_email(form_data.email.lower())
Timothy J. Baek's avatar
Timothy J. Baek committed
164
165
166
167
168
169
170
171
            if email_user:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail=ERROR_MESSAGES.EMAIL_TAKEN,
                )

        if form_data.password:
            hashed = get_password_hash(form_data.password)
172
            log.debug(f"hashed: {hashed}")
Timothy J. Baek's avatar
Timothy J. Baek committed
173
174
            Auths.update_user_password_by_id(user_id, hashed)

Timothy J. Baek's avatar
Timothy J. Baek committed
175
        Auths.update_email_by_id(user_id, form_data.email.lower())
Timothy J. Baek's avatar
Timothy J. Baek committed
176
177
178
179
        updated_user = Users.update_user_by_id(
            user_id,
            {
                "name": form_data.name,
Timothy J. Baek's avatar
Timothy J. Baek committed
180
                "email": form_data.email.lower(),
Timothy J. Baek's avatar
Timothy J. Baek committed
181
182
183
184
185
186
187
                "profile_image_url": form_data.profile_image_url,
            },
        )

        if updated_user:
            return updated_user

Timothy J. Baek's avatar
Timothy J. Baek committed
188
        raise HTTPException(
Timothy J. Baek's avatar
Timothy J. Baek committed
189
            status_code=status.HTTP_400_BAD_REQUEST,
190
            detail=ERROR_MESSAGES.DEFAULT(),
Timothy J. Baek's avatar
Timothy J. Baek committed
191
        )
192

193
194
195
196
197
    raise HTTPException(
        status_code=status.HTTP_400_BAD_REQUEST,
        detail=ERROR_MESSAGES.USER_NOT_FOUND,
    )

198
199

############################
Timothy J. Baek's avatar
Timothy J. Baek committed
200
# DeleteUserById
201
202
203
204
############################


@router.delete("/{user_id}", response_model=bool)
205
206
207
208
209
210
211
async def delete_user_by_id(user_id: str, user=Depends(get_admin_user)):
    if user.id != user_id:
        result = Auths.delete_auth_by_id(user_id)

        if result:
            return True

212
        raise HTTPException(
213
214
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=ERROR_MESSAGES.DELETE_USER_ERROR,
215
        )
216
217
218
219
220

    raise HTTPException(
        status_code=status.HTTP_403_FORBIDDEN,
        detail=ERROR_MESSAGES.ACTION_PROHIBITED,
    )