open-webui/backend/open_webui/models/users.py

459 lines
13 KiB
Python
Raw Normal View History

2023-11-19 00:47:12 +00:00
import time
2024-08-27 22:10:27 +00:00
from typing import Optional
2024-12-10 08:54:13 +00:00
from open_webui.internal.db import Base, JSONField, get_db
2025-01-21 07:20:47 +00:00
2025-08-17 00:06:16 +00:00
from open_webui.env import DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL
2024-12-10 08:54:13 +00:00
from open_webui.models.chats import Chats
2025-01-21 07:20:47 +00:00
from open_webui.models.groups import Groups
2025-08-17 00:06:16 +00:00
from open_webui.utils.misc import throttle
2025-01-21 07:20:47 +00:00
2024-08-27 22:10:27 +00:00
from pydantic import BaseModel, ConfigDict
2025-08-20 22:39:25 +00:00
from sqlalchemy import BigInteger, Column, String, Text, Date
2025-04-30 12:49:41 +00:00
from sqlalchemy import or_
2025-08-20 22:39:25 +00:00
import datetime
2023-12-29 07:02:49 +00:00
2023-11-19 00:47:12 +00:00
####################
# User DB Schema
####################
class User(Base):
__tablename__ = "user"
2024-04-27 23:38:51 +00:00
id = Column(String, primary_key=True)
name = Column(String)
2025-08-20 22:39:25 +00:00
email = Column(String)
2025-08-20 22:39:25 +00:00
username = Column(String(50), nullable=True)
role = Column(String)
profile_image_url = Column(Text)
2024-04-27 23:38:51 +00:00
2025-08-20 22:39:25 +00:00
bio = Column(Text, nullable=True)
gender = Column(Text, nullable=True)
date_of_birth = Column(Date, nullable=True)
2023-12-26 05:44:28 +00:00
info = Column(JSONField, nullable=True)
2025-08-20 22:39:25 +00:00
settings = Column(JSONField, nullable=True)
2025-08-20 22:39:25 +00:00
api_key = Column(String, nullable=True, unique=True)
oauth_sub = Column(Text, unique=True)
2023-12-26 05:44:28 +00:00
2025-08-20 22:39:25 +00:00
last_active_at = Column(BigInteger)
updated_at = Column(BigInteger)
created_at = Column(BigInteger)
2023-12-26 05:44:28 +00:00
2024-05-27 05:47:42 +00:00
class UserSettings(BaseModel):
ui: Optional[dict] = {}
model_config = ConfigDict(extra="allow")
pass
2023-11-19 00:47:12 +00:00
class UserModel(BaseModel):
id: str
name: str
2025-08-20 22:39:25 +00:00
2023-11-19 00:47:12 +00:00
email: str
2025-08-20 22:39:25 +00:00
username: Optional[str] = None
2023-11-19 05:41:43 +00:00
role: str = "pending"
profile_image_url: str
2024-04-27 23:38:51 +00:00
2025-08-20 22:39:25 +00:00
bio: Optional[str] = None
gender: Optional[str] = None
date_of_birth: Optional[datetime.date] = None
2024-04-27 23:38:51 +00:00
2024-06-16 22:32:26 +00:00
info: Optional[dict] = None
2025-08-20 22:39:25 +00:00
settings: Optional[UserSettings] = None
2023-11-19 00:47:12 +00:00
2025-08-20 22:39:25 +00:00
api_key: Optional[str] = None
oauth_sub: Optional[str] = None
2025-08-20 22:39:25 +00:00
last_active_at: int # timestamp in epoch
updated_at: int # timestamp in epoch
created_at: int # timestamp in epoch
model_config = ConfigDict(from_attributes=True)
2023-11-19 00:47:12 +00:00
####################
# Forms
####################
2025-08-20 22:39:25 +00:00
class UpdateProfileForm(BaseModel):
profile_image_url: str
name: str
bio: Optional[str] = None
gender: Optional[str] = None
date_of_birth: Optional[datetime.date] = None
2025-04-30 12:49:41 +00:00
class UserListResponse(BaseModel):
users: list[UserModel]
total: int
2025-07-18 07:46:14 +00:00
class UserInfoResponse(BaseModel):
id: str
name: str
email: str
role: str
2025-09-17 02:41:47 +00:00
class UserIdNameResponse(BaseModel):
id: str
name: str
2025-07-18 07:46:14 +00:00
class UserInfoListResponse(BaseModel):
users: list[UserInfoResponse]
total: int
2025-09-17 02:41:47 +00:00
class UserIdNameListResponse(BaseModel):
users: list[UserIdNameResponse]
total: int
2024-11-18 13:37:04 +00:00
class UserResponse(BaseModel):
id: str
name: str
email: str
role: str
profile_image_url: str
2024-12-23 04:50:14 +00:00
class UserNameResponse(BaseModel):
id: str
name: str
role: str
profile_image_url: str
2023-11-19 08:13:59 +00:00
class UserRoleUpdateForm(BaseModel):
id: str
role: str
2024-01-06 04:59:56 +00:00
class UserUpdateForm(BaseModel):
2025-05-31 11:00:27 +00:00
role: str
2024-01-06 04:59:56 +00:00
name: str
email: str
profile_image_url: str
password: Optional[str] = None
2024-01-06 04:59:56 +00:00
class UsersTable:
def insert_new_user(
2024-04-04 08:10:51 +00:00
self,
id: str,
name: str,
email: str,
2024-04-07 06:16:29 +00:00
profile_image_url: str = "/user.png",
2024-04-04 08:10:51 +00:00
role: str = "pending",
oauth_sub: Optional[str] = None,
2024-01-06 04:59:56 +00:00
) -> Optional[UserModel]:
2024-07-04 06:32:39 +00:00
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
def get_user_by_id(self, id: str) -> Optional[UserModel]:
try:
2024-07-04 06:32:39 +00:00
with get_db() as db:
user = db.query(User).filter_by(id=id).first()
return UserModel.model_validate(user)
2024-08-27 22:10:27 +00:00
except Exception:
return None
def get_user_by_api_key(self, api_key: str) -> Optional[UserModel]:
try:
2024-07-04 06:32:39 +00:00
with get_db() as db:
user = db.query(User).filter_by(api_key=api_key).first()
return UserModel.model_validate(user)
2024-08-14 12:38:19 +00:00
except Exception:
return None
def get_user_by_email(self, email: str) -> Optional[UserModel]:
try:
2024-07-04 06:32:39 +00:00
with get_db() as db:
user = db.query(User).filter_by(email=email).first()
return UserModel.model_validate(user)
2024-08-14 12:38:19 +00:00
except Exception:
return None
2023-11-19 00:47:12 +00:00
def get_user_by_oauth_sub(self, sub: str) -> Optional[UserModel]:
try:
2024-07-04 06:32:39 +00:00
with get_db() as db:
user = db.query(User).filter_by(oauth_sub=sub).first()
return UserModel.model_validate(user)
2024-08-14 12:38:19 +00:00
except Exception:
return None
2024-12-25 07:53:25 +00:00
def get_users(
self,
2025-04-30 12:49:41 +00:00
filter: Optional[dict] = None,
skip: Optional[int] = None,
limit: Optional[int] = None,
2025-04-30 12:49:41 +00:00
) -> UserListResponse:
2024-07-04 06:32:39 +00:00
with get_db() as db:
2025-04-30 12:49:41 +00:00
query = db.query(User)
2024-12-25 07:53:25 +00:00
2025-04-30 12:49:41 +00:00
if filter:
query_key = filter.get("query")
if query_key:
query = query.filter(
or_(
2025-04-30 12:49:41 +00:00
User.name.ilike(f"%{query_key}%"),
User.email.ilike(f"%{query_key}%"),
)
)
2025-04-30 12:49:41 +00:00
order_by = filter.get("order_by")
direction = filter.get("direction")
if order_by == "name":
if direction == "asc":
query = query.order_by(User.name.asc())
else:
query = query.order_by(User.name.desc())
elif order_by == "email":
if direction == "asc":
query = query.order_by(User.email.asc())
else:
query = query.order_by(User.email.desc())
elif order_by == "created_at":
if direction == "asc":
query = query.order_by(User.created_at.asc())
else:
query = query.order_by(User.created_at.desc())
elif order_by == "last_active_at":
if direction == "asc":
query = query.order_by(User.last_active_at.asc())
else:
query = query.order_by(User.last_active_at.desc())
elif order_by == "updated_at":
if direction == "asc":
query = query.order_by(User.updated_at.asc())
else:
query = query.order_by(User.updated_at.desc())
elif order_by == "role":
if direction == "asc":
query = query.order_by(User.role.asc())
else:
query = query.order_by(User.role.desc())
else:
query = query.order_by(User.created_at.desc())
2024-12-25 07:53:25 +00:00
if skip:
query = query.offset(skip)
if limit:
query = query.limit(limit)
users = query.all()
2025-04-30 12:49:41 +00:00
return {
"users": [UserModel.model_validate(user) for user in users],
"total": db.query(User).count(),
}
2024-12-25 07:53:25 +00:00
def get_users_by_user_ids(self, user_ids: list[str]) -> list[UserModel]:
with get_db() as db:
users = db.query(User).filter(User.id.in_(user_ids)).all()
2024-07-04 06:32:39 +00:00
return [UserModel.model_validate(user) for user in users]
def get_num_users(self) -> Optional[int]:
2024-07-04 06:32:39 +00:00
with get_db() as db:
return db.query(User).count()
def has_users(self) -> bool:
with get_db() as db:
return db.query(db.query(User).exists()).scalar()
def get_first_user(self) -> UserModel:
try:
2024-07-04 06:32:39 +00:00
with get_db() as db:
user = db.query(User).order_by(User.created_at).first()
return UserModel.model_validate(user)
2024-08-14 12:38:19 +00:00
except Exception:
return None
2024-12-21 06:54:43 +00:00
def get_user_webhook_url_by_id(self, id: str) -> Optional[str]:
try:
with get_db() as db:
user = db.query(User).filter_by(id=id).first()
2024-12-25 07:53:25 +00:00
if user.settings is None:
return None
else:
return (
user.settings.get("ui", {})
.get("notifications", {})
.get("webhook_url", None)
)
2024-12-21 06:54:43 +00:00
except Exception:
return None
2024-06-24 07:57:08 +00:00
def update_user_role_by_id(self, id: str, role: str) -> Optional[UserModel]:
try:
2024-07-04 06:32:39 +00:00
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)
2024-08-14 12:38:19 +00:00
except Exception:
return None
2023-11-19 08:13:59 +00:00
2024-01-27 04:27:45 +00:00
def update_user_profile_image_url_by_id(
self, id: str, profile_image_url: str
2024-01-27 04:27:45 +00:00
) -> Optional[UserModel]:
try:
2024-07-04 06:32:39 +00:00
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)
2024-08-14 12:38:19 +00:00
except Exception:
return None
2024-01-27 04:27:45 +00:00
2025-08-17 00:06:16 +00:00
@throttle(DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL)
2024-06-24 07:57:08 +00:00
def update_user_last_active_by_id(self, id: str) -> Optional[UserModel]:
try:
2024-07-04 06:32:39 +00:00
with get_db() as db:
db.query(User).filter_by(id=id).update(
{"last_active_at": int(time.time())}
)
db.commit()
2024-04-27 23:38:51 +00:00
2024-07-04 06:32:39 +00:00
user = db.query(User).filter_by(id=id).first()
return UserModel.model_validate(user)
2024-08-14 12:38:19 +00:00
except Exception:
return None
2024-04-27 23:38:51 +00:00
def update_user_oauth_sub_by_id(
self, id: str, oauth_sub: str
) -> Optional[UserModel]:
try:
2024-07-04 06:32:39 +00:00
with get_db() as db:
db.query(User).filter_by(id=id).update({"oauth_sub": oauth_sub})
2024-07-08 06:01:15 +00:00
db.commit()
2024-07-04 06:32:39 +00:00
user = db.query(User).filter_by(id=id).first()
return UserModel.model_validate(user)
2024-08-14 12:38:19 +00:00
except Exception:
return None
2024-06-24 07:57:08 +00:00
def update_user_by_id(self, id: str, updated: dict) -> Optional[UserModel]:
try:
2024-07-04 06:32:39 +00:00
with get_db() as db:
db.query(User).filter_by(id=id).update(updated)
db.commit()
2024-01-06 04:59:56 +00:00
2024-07-04 06:32:39 +00:00
user = db.query(User).filter_by(id=id).first()
return UserModel.model_validate(user)
# return UserModel(**user.dict())
2025-08-20 22:39:25 +00:00
except Exception as e:
print(e)
return None
2025-02-12 07:42:31 +00:00
def update_user_settings_by_id(self, id: str, updated: dict) -> Optional[UserModel]:
try:
with get_db() as db:
user_settings = db.query(User).filter_by(id=id).first().settings
if user_settings is None:
user_settings = {}
user_settings.update(updated)
db.query(User).filter_by(id=id).update({"settings": user_settings})
db.commit()
user = db.query(User).filter_by(id=id).first()
return UserModel.model_validate(user)
except Exception:
return None
def delete_user_by_id(self, id: str) -> bool:
try:
2025-01-21 07:20:47 +00:00
# Remove User from Groups
Groups.remove_user_from_all_groups(id)
# Delete User Chats
result = Chats.delete_chats_by_user_id(id)
if result:
2024-07-04 06:32:39 +00:00
with get_db() as db:
# Delete User
db.query(User).filter_by(id=id).delete()
db.commit()
return True
else:
return False
2024-08-14 12:38:19 +00:00
except Exception:
return False
2023-12-29 07:02:49 +00:00
2025-06-10 12:20:57 +00:00
def update_user_api_key_by_id(self, id: str, api_key: str) -> bool:
try:
2024-07-04 06:32:39 +00:00
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
2024-08-14 12:38:19 +00:00
except Exception:
return False
2023-12-29 07:02:49 +00:00
def get_user_api_key_by_id(self, id: str) -> Optional[str]:
try:
2024-07-04 06:32:39 +00:00
with get_db() as db:
user = db.query(User).filter_by(id=id).first()
return user.api_key
2024-08-27 22:10:27 +00:00
except Exception:
return None
2024-04-02 16:27:35 +00:00
def get_valid_user_ids(self, user_ids: list[str]) -> list[str]:
with get_db() as db:
users = db.query(User).filter(User.id.in_(user_ids)).all()
return [user.id for user in users]
2025-05-05 15:38:36 +00:00
def get_super_admin_user(self) -> Optional[UserModel]:
with get_db() as db:
user = db.query(User).filter_by(role="admin").first()
if user:
return UserModel.model_validate(user)
else:
return None
2023-11-19 00:47:12 +00:00
Users = UsersTable()