users.py 6.88 KB
Newer Older
1
from pydantic import BaseModel, ConfigDict, parse_obj_as
2
3
from typing import List, Union, Optional
import time
4
5
6

from sqlalchemy import String, Column, BigInteger, Text

Timothy J. Baek's avatar
Timothy J. Baek committed
7
8
from utils.misc import get_gravatar_url

9
from apps.webui.internal.db import Base, JSONField, Session
10
from apps.webui.models.chats import Chats
11

12
13
14
15
16
####################
# User DB Schema
####################


17
18
class User(Base):
    __tablename__ = "user"
Timothy J. Baek's avatar
Timothy J. Baek committed
19

20
21
22
23
24
    id = Column(String, primary_key=True)
    name = Column(String)
    email = Column(String)
    role = Column(String)
    profile_image_url = Column(String)
Timothy J. Baek's avatar
Timothy J. Baek committed
25

26
27
28
    last_active_at = Column(BigInteger)
    updated_at = Column(BigInteger)
    created_at = Column(BigInteger)
Timothy J. Baek's avatar
Timothy J. Baek committed
29

30
31
32
    api_key = Column(String, nullable=True, unique=True)
    settings = Column(JSONField, nullable=True)
    info = Column(JSONField, nullable=True)
33

34
    oauth_sub = Column(Text, unique=True)
Timothy J. Baek's avatar
Timothy J. Baek committed
35
36


37
38
39
40
41
42
class UserSettings(BaseModel):
    ui: Optional[dict] = {}
    model_config = ConfigDict(extra="allow")
    pass


43
44
45
46
class UserModel(BaseModel):
    id: str
    name: str
    email: str
Timothy J. Baek's avatar
Timothy J. Baek committed
47
    role: str = "pending"
48
    profile_image_url: str
Timothy J. Baek's avatar
Timothy J. Baek committed
49
50
51
52
53

    last_active_at: int  # timestamp in epoch
    updated_at: int  # timestamp in epoch
    created_at: int  # timestamp in epoch

54
    api_key: Optional[str] = None
55
    settings: Optional[UserSettings] = None
Timothy J. Baek's avatar
Timothy J. Baek committed
56
    info: Optional[dict] = None
57

58
59
    oauth_sub: Optional[str] = None

60
61
    model_config = ConfigDict(from_attributes=True)

62
63
64
65
66
67

####################
# Forms
####################


Timothy J. Baek's avatar
Timothy J. Baek committed
68
69
70
71
72
class UserRoleUpdateForm(BaseModel):
    id: str
    role: str


Timothy J. Baek's avatar
Timothy J. Baek committed
73
74
75
76
77
78
class UserUpdateForm(BaseModel):
    name: str
    email: str
    profile_image_url: str
    password: Optional[str] = None

79

Timothy J. Baek's avatar
Timothy J. Baek committed
80
class UsersTable:
81

Timothy J. Baek's avatar
Timothy J. Baek committed
82
    def insert_new_user(
Danny Liu's avatar
Danny Liu committed
83
84
85
86
        self,
        id: str,
        name: str,
        email: str,
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
87
        profile_image_url: str = "/user.png",
Danny Liu's avatar
Danny Liu committed
88
        role: str = "pending",
89
        oauth_sub: Optional[str] = None,
Timothy J. Baek's avatar
Timothy J. Baek committed
90
    ) -> Optional[UserModel]:
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
        user = UserModel(
            **{
                "id": id,
                "name": name,
                "email": email,
                "role": role,
                "profile_image_url": profile_image_url,
                "last_active_at": int(time.time()),
                "created_at": int(time.time()),
                "updated_at": int(time.time()),
                "oauth_sub": oauth_sub,
            }
        )
        result = User(**user.model_dump())
        Session.add(result)
        Session.commit()
        Session.refresh(result)
        if result:
            return user
        else:
            return None
112
113

    def get_user_by_id(self, id: str) -> Optional[UserModel]:
114
115
116
117
118
        try:
            user = Session.query(User).filter_by(id=id).first()
            return UserModel.model_validate(user)
        except Exception as e:
            return None
119
120

    def get_user_by_api_key(self, api_key: str) -> Optional[UserModel]:
121
122
123
124
125
        try:
            user = Session.query(User).filter_by(api_key=api_key).first()
            return UserModel.model_validate(user)
        except:
            return None
126
127

    def get_user_by_email(self, email: str) -> Optional[UserModel]:
128
129
130
131
132
        try:
            user = Session.query(User).filter_by(email=email).first()
            return UserModel.model_validate(user)
        except:
            return None
133

134
    def get_user_by_oauth_sub(self, sub: str) -> Optional[UserModel]:
135
136
137
138
139
        try:
            user = Session.query(User).filter_by(oauth_sub=sub).first()
            return UserModel.model_validate(user)
        except:
            return None
140
141

    def get_users(self, skip: int = 0, limit: int = 50) -> List[UserModel]:
142
143
144
145
146
147
        users = (
            Session.query(User)
            # .offset(skip).limit(limit)
            .all()
        )
        return [UserModel.model_validate(user) for user in users]
148
149

    def get_num_users(self) -> Optional[int]:
150
        return Session.query(User).count()
151
152

    def get_first_user(self) -> UserModel:
153
154
155
156
157
        try:
            user = Session.query(User).order_by(User.created_at).first()
            return UserModel.model_validate(user)
        except:
            return None
158

159
    def update_user_role_by_id(self, id: str, role: str) -> Optional[UserModel]:
160
161
162
        try:
            Session.query(User).filter_by(id=id).update({"role": role})
            Session.commit()
Timothy J. Baek's avatar
Timothy J. Baek committed
163

164
165
166
167
            user = Session.query(User).filter_by(id=id).first()
            return UserModel.model_validate(user)
        except:
            return None
Timothy J. Baek's avatar
Timothy J. Baek committed
168

169
    def update_user_profile_image_url_by_id(
170
        self, id: str, profile_image_url: str
171
    ) -> Optional[UserModel]:
172
173
174
175
176
177
178
179
180
181
        try:
            Session.query(User).filter_by(id=id).update(
                {"profile_image_url": profile_image_url}
            )
            Session.commit()

            user = Session.query(User).filter_by(id=id).first()
            return UserModel.model_validate(user)
        except:
            return None
182

183
    def update_user_last_active_by_id(self, id: str) -> Optional[UserModel]:
184
185
186
187
        try:
            Session.query(User).filter_by(id=id).update(
                {"last_active_at": int(time.time())}
            )
Timothy J. Baek's avatar
Timothy J. Baek committed
188

189
190
191
192
            user = Session.query(User).filter_by(id=id).first()
            return UserModel.model_validate(user)
        except:
            return None
Timothy J. Baek's avatar
Timothy J. Baek committed
193

194
    def update_user_oauth_sub_by_id(
195
        self, id: str, oauth_sub: str
196
    ) -> Optional[UserModel]:
197
198
        try:
            Session.query(User).filter_by(id=id).update({"oauth_sub": oauth_sub})
199

200
201
202
203
            user = Session.query(User).filter_by(id=id).first()
            return UserModel.model_validate(user)
        except:
            return None
204

205
    def update_user_by_id(self, id: str, updated: dict) -> Optional[UserModel]:
206
207
208
        try:
            Session.query(User).filter_by(id=id).update(updated)
            Session.commit()
Timothy J. Baek's avatar
Timothy J. Baek committed
209

210
211
212
213
214
            user = Session.query(User).filter_by(id=id).first()
            return UserModel.model_validate(user)
            # return UserModel(**user.dict())
        except Exception as e:
            return None
215
216

    def delete_user_by_id(self, id: str) -> bool:
217
218
219
220
221
222
223
224
225
226
227
        try:
            # Delete User Chats
            result = Chats.delete_chats_by_user_id(id)

            if result:
                # Delete User
                Session.query(User).filter_by(id=id).delete()
                Session.commit()

                return True
            else:
228
                return False
229
230
        except:
            return False
231

232
    def update_user_api_key_by_id(self, id: str, api_key: str) -> str:
233
234
235
236
237
238
        try:
            result = Session.query(User).filter_by(id=id).update({"api_key": api_key})
            Session.commit()
            return True if result == 1 else False
        except:
            return False
239

240
    def get_user_api_key_by_id(self, id: str) -> Optional[str]:
241
242
243
244
245
        try:
            user = Session.query(User).filter_by(id=id).first()
            return user.api_key
        except Exception as e:
            return None
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
246

247

248
Users = UsersTable()