users.py 7.56 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

Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
9
from apps.webui.internal.db import Base, JSONField, Session, get_db
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
    id = Column(String, primary_key=True)
    name = Column(String)
    email = Column(String)
    role = Column(String)
24
    profile_image_url = Column(Text)
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]:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
        with get_db() as db:
            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())
            db.add(result)
            db.commit()
            db.refresh(result)
            if result:
                return user
            else:
                return None
113
114

    def get_user_by_id(self, id: str) -> Optional[UserModel]:
115
        try:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
116
117
118
            with get_db() as db:
                user = db.query(User).filter_by(id=id).first()
                return UserModel.model_validate(user)
119
120
        except Exception as e:
            return None
121
122

    def get_user_by_api_key(self, api_key: str) -> Optional[UserModel]:
123
        try:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
124
125
126
127
            with get_db() as db:

                user = db.query(User).filter_by(api_key=api_key).first()
                return UserModel.model_validate(user)
128
129
        except:
            return None
130
131

    def get_user_by_email(self, email: str) -> Optional[UserModel]:
132
        try:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
133
134
135
136
            with get_db() as db:

                user = db.query(User).filter_by(email=email).first()
                return UserModel.model_validate(user)
137
138
        except:
            return None
139

140
    def get_user_by_oauth_sub(self, sub: str) -> Optional[UserModel]:
141
        try:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
142
143
144
145
            with get_db() as db:

                user = db.query(User).filter_by(oauth_sub=sub).first()
                return UserModel.model_validate(user)
146
147
        except:
            return None
148
149

    def get_users(self, skip: int = 0, limit: int = 50) -> List[UserModel]:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
150
151
152
153
154
155
156
        with get_db() as db:
            users = (
                db.query(User)
                # .offset(skip).limit(limit)
                .all()
            )
            return [UserModel.model_validate(user) for user in users]
157
158

    def get_num_users(self) -> Optional[int]:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
159
160
        with get_db() as db:
            return db.query(User).count()
161
162

    def get_first_user(self) -> UserModel:
163
        try:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
164
165
166
            with get_db() as db:
                user = db.query(User).order_by(User.created_at).first()
                return UserModel.model_validate(user)
167
168
        except:
            return None
169

170
    def update_user_role_by_id(self, id: str, role: str) -> Optional[UserModel]:
171
        try:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
172
173
174
175
176
            with get_db() as db:
                db.query(User).filter_by(id=id).update({"role": role})
                db.commit()
                user = db.query(User).filter_by(id=id).first()
                return UserModel.model_validate(user)
177
178
        except:
            return None
Timothy J. Baek's avatar
Timothy J. Baek committed
179

180
    def update_user_profile_image_url_by_id(
181
        self, id: str, profile_image_url: str
182
    ) -> Optional[UserModel]:
183
        try:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
184
185
186
187
188
189
190
191
            with get_db() as db:
                db.query(User).filter_by(id=id).update(
                    {"profile_image_url": profile_image_url}
                )
                db.commit()

                user = db.query(User).filter_by(id=id).first()
                return UserModel.model_validate(user)
192
193
        except:
            return None
194

195
    def update_user_last_active_by_id(self, id: str) -> Optional[UserModel]:
196
        try:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
197
198
199
200
201
202
            with get_db() as db:

                db.query(User).filter_by(id=id).update(
                    {"last_active_at": int(time.time())}
                )
                db.commit()
Timothy J. Baek's avatar
Timothy J. Baek committed
203

Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
204
205
                user = db.query(User).filter_by(id=id).first()
                return UserModel.model_validate(user)
206
207
        except:
            return None
Timothy J. Baek's avatar
Timothy J. Baek committed
208

209
    def update_user_oauth_sub_by_id(
210
        self, id: str, oauth_sub: str
211
    ) -> Optional[UserModel]:
212
        try:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
213
214
            with get_db() as db:
                db.query(User).filter_by(id=id).update({"oauth_sub": oauth_sub})
215

Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
216
217
                user = db.query(User).filter_by(id=id).first()
                return UserModel.model_validate(user)
218
219
        except:
            return None
220

221
    def update_user_by_id(self, id: str, updated: dict) -> Optional[UserModel]:
222
        try:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
223
224
225
            with get_db() as db:
                db.query(User).filter_by(id=id).update(updated)
                db.commit()
Timothy J. Baek's avatar
Timothy J. Baek committed
226

Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
227
228
229
                user = db.query(User).filter_by(id=id).first()
                return UserModel.model_validate(user)
                # return UserModel(**user.dict())
230
231
        except Exception as e:
            return None
232
233

    def delete_user_by_id(self, id: str) -> bool:
234
235
236
237
238
        try:
            # Delete User Chats
            result = Chats.delete_chats_by_user_id(id)

            if result:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
239
240
241
242
                with get_db() as db:
                    # Delete User
                    db.query(User).filter_by(id=id).delete()
                    db.commit()
243
244
245

                return True
            else:
246
                return False
247
248
        except:
            return False
249

250
    def update_user_api_key_by_id(self, id: str, api_key: str) -> str:
251
        try:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
252
253
254
255
            with get_db() as db:
                result = db.query(User).filter_by(id=id).update({"api_key": api_key})
                db.commit()
                return True if result == 1 else False
256
257
        except:
            return False
258

259
    def get_user_api_key_by_id(self, id: str) -> Optional[str]:
260
        try:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
261
262
263
            with get_db() as db:
                user = db.query(User).filter_by(id=id).first()
                return user.api_key
264
265
        except Exception as e:
            return None
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
266

267

268
Users = UsersTable()