Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -310,3 +310,5 @@ dist
cypress/videos
cypress/screenshots
.vscode/settings.json
backend/open_webui/static/*
backend/open_webui/frontend/*
5 changes: 3 additions & 2 deletions backend/dev.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export CORS_ALLOW_ORIGIN="http://localhost:5173"
#export CORS_ALLOW_ORIGIN="http://localhost:5173"
export PYTHONPATH=$PYTHONPATH:/home/ubuntu/squadrun-open-webui/backend
PORT="${PORT:-8080}"
uvicorn open_webui.main:app --port $PORT --host 0.0.0.0 --forwarded-allow-ips '*' --reload
uvicorn open_webui.main:app --port $PORT --host 0.0.0.0 --forwarded-allow-ips '*'
6 changes: 5 additions & 1 deletion backend/open_webui/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,10 @@
FROM_INIT_PY = os.environ.get("FROM_INIT_PY", "False").lower() == "true"

if FROM_INIT_PY:
PACKAGE_DATA = {"version": importlib.metadata.version("open-webui")}
try:
PACKAGE_DATA = {"version": importlib.metadata.version("open-webui")}
except importlib.metadata.PackageNotFoundError:
PACKAGE_DATA = {"version": "prod"} # fallback for running from folder
else:
try:
PACKAGE_DATA = json.loads((BASE_DIR / "package.json").read_text())
Expand Down Expand Up @@ -790,3 +793,4 @@ def parse_section(section):
####################################

EXTERNAL_PWA_MANIFEST_URL = os.environ.get("EXTERNAL_PWA_MANIFEST_URL")
SENTRY_DSN = os.environ.get("SENTRY_DSN", "")
19 changes: 18 additions & 1 deletion backend/open_webui/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

from contextlib import asynccontextmanager
from urllib.parse import urlencode, parse_qs, urlparse

import sentry_sdk
from pydantic import BaseModel
from sqlalchemy import text

Expand Down Expand Up @@ -434,7 +436,7 @@
ENABLE_VERSION_UPDATE_CHECK,
ENABLE_OTEL,
EXTERNAL_PWA_MANIFEST_URL,
AIOHTTP_CLIENT_SESSION_SSL,
AIOHTTP_CLIENT_SESSION_SSL, SENTRY_DSN,
)


Expand Down Expand Up @@ -918,6 +920,17 @@ async def lifespan(app: FastAPI):
app.state.YOUTUBE_LOADER_TRANSLATION = None


sentry_sdk.init(
dsn=SENTRY_DSN,
# Add data like request headers and IP for users,
# see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info
send_default_pii=True,
# Set traces_sample_rate to 1.0 to capture 100%
# of transactions for tracing.
traces_sample_rate=0.1,
)


try:
app.state.ef = get_ef(
app.state.config.RAG_EMBEDDING_ENGINE,
Expand Down Expand Up @@ -1158,6 +1171,10 @@ async def dispatch(self, request: Request, call_next):
app.add_middleware(RedirectMiddleware)
app.add_middleware(SecurityHeadersMiddleware)

@app.get("/sentry-debug")
async def trigger_error():
division_by_zero = 1 / 0


@app.middleware("http")
async def commit_session_after_request(request: Request, call_next):
Expand Down
3 changes: 3 additions & 0 deletions backend/open_webui/models/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ def insert_new_user(
db.commit()
db.refresh(result)
if result:
# Assign user to default group if specified
from open_webui.utils.user_groups import assign_user_to_default_group
assign_user_to_default_group(user.id, user.email)
return user
else:
return None
Expand Down
60 changes: 60 additions & 0 deletions backend/open_webui/utils/user_groups.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""
Utility functions for user group management.
This module handles default group assignment for newly created users.
"""

import logging
from typing import Optional

from open_webui.env import SRC_LOG_LEVELS

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


def assign_user_to_default_group(user_id: str, user_email: str) -> bool:
"""
Assign a user to the default group if one is configured.

Args:
user_id: The ID of the user to assign
user_email: The email of the user (for logging purposes)

Returns:
bool: True if assignment was successful or no default group is configured, False if assignment failed
"""
try:
import os
from open_webui.models.groups import Groups

# Read directly from environment variable
group_name = os.getenv("DEFAULT_USER_GROUP", "").strip()

# Check if a default group is configured
if not group_name:
return True # No default group configured, consider this successful

# Find the group by name
groups = Groups.get_groups()
default_group = None
for group in groups:
if group.name == group_name:
default_group = group
break

if not default_group:
log.warning(f"Default group '{group_name}' not found. User {user_email} not assigned to any group.")
return False

# Add user to the group
updated_group = Groups.add_users_to_group(default_group.id, [user_id])
if updated_group:
log.info(f"Assigned user {user_email} to default group: {group_name}")
return True
else:
log.error(f"Failed to add user {user_email} to default group: {group_name}")
return False

except Exception as e:
log.error(f"Failed to assign user {user_email} to default group: {str(e)}")
return False
1 change: 1 addition & 0 deletions backend/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ aiocache
aiofiles
starlette-compress==1.6.0
httpx[socks,http2,zstd,cli,brotli]==0.28.1
sentry-sdk[fastapi]==2.37.1

sqlalchemy==2.0.38
alembic==1.14.0
Expand Down
26 changes: 1 addition & 25 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ dependencies = [
"uvicorn[standard]==0.35.0",
"pydantic==2.11.7",
"python-multipart==0.0.20",

"python-socketio==5.13.0",
"python-jose==3.4.0",
"passlib[bcrypt]==1.7.4",
Expand All @@ -19,41 +18,32 @@ dependencies = [
"argon2-cffi==23.1.0",
"PyJWT[crypto]==2.10.1",
"authlib==1.6.1",

"requests==2.32.4",
"aiohttp==3.12.15",
"async-timeout",
"aiocache",
"aiofiles",
"starlette-compress==1.6.0",
"httpx[socks,http2,zstd,cli,brotli]==0.28.1",

"sqlalchemy==2.0.38",
"alembic==1.14.0",
"peewee==3.18.1",
"peewee-migrate==1.12.2",

"pycrdt==0.12.25",
"redis",

"PyMySQL==1.1.1",
"boto3==1.40.5",

"APScheduler==3.10.4",
"RestrictedPython==8.0",

"loguru==0.7.3",
"asgiref==3.8.1",

"tiktoken",
"openai",
"anthropic",
"google-genai==1.32.0",
"google-generativeai==0.8.5",

"langchain==0.3.26",
"langchain-community==0.3.26",

"fake-useragent==2.2.0",
"chromadb==0.6.3",
"pymilvus==2.5.0",
Expand All @@ -63,14 +53,12 @@ dependencies = [
"elasticsearch==9.0.1",
"pinecone==6.0.2",
"oracledb==3.2.0",

"transformers",
"sentence-transformers==4.1.0",
"accelerate",
"colbert-ai==0.2.21",
"pyarrow==20.0.0",
"einops==0.8.1",

"ftfy==6.2.3",
"pypdf==4.3.1",
"fpdf2==2.8.2",
Expand All @@ -90,42 +78,30 @@ dependencies = [
"sentencepiece",
"soundfile==0.13.1",
"azure-ai-documentintelligence==1.0.2",

"pillow==11.3.0",
"opencv-python-headless==4.11.0.86",
"rapidocr-onnxruntime==1.4.4",
"rank-bm25==0.2.2",

"onnxruntime==1.20.1",
"faster-whisper==1.1.1",

"black==25.1.0",
"youtube-transcript-api==1.1.0",
"pytube==15.0.0",

"pydub",
"ddgs==9.0.0",

"google-api-python-client",
"google-auth-httplib2",
"google-auth-oauthlib",



"googleapis-common-protos==1.63.2",
"google-cloud-storage==2.19.0",

"azure-identity==1.20.0",
"azure-storage-blob==12.24.1",

"ldap3==2.9.1",

"firecrawl-py==1.12.0",
"tencentcloud-sdk-python==3.0.1336",

"oracledb>=3.2.0",
"posthog==5.4.0",

"sentry-sdk[fastapi]>=2.37.1",
]
readme = "README.md"
requires-python = ">= 3.11, < 3.13.0a1"
Expand Down
Loading