From 9451b13dc632e76c484cede8104722ace4acb0da Mon Sep 17 00:00:00 2001
From: Classic298 <27028174+Classic298@users.noreply.github.com>
Date: Thu, 8 Jan 2026 21:55:57 +0100
Subject: [PATCH] feat: add ENABLE_USER_STATUS toggle for admin-controlled user
status visibility (#20488)
* feat: add ENABLE_USER_STATUS toggle for admin-controlled user status visibility
feat: add ENABLE_USER_STATUS toggle for admin-controlled user status visibility
Add a new admin panel toggle (Admin > Settings > General) called "User Status" that allows administrators to globally enable or disable user status functionality.
When disabled:
- User status API endpoints return 403 Forbidden
- Status emoji, message, and "Update your status" button are hidden from the user menu
The setting:
- Defaults to True (enabled)
- Can be overridden via ENABLE_USER_STATUS environment variable
- Persists across restarts using PersistentConfig
Files modified:
- backend/open_webui/config.py - Added ENABLE_USER_STATUS PersistentConfig
- backend/open_webui/main.py - App state init and features dict
- backend/open_webui/routers/auths.py - AdminConfig model and endpoints
- backend/open_webui/routers/users.py - 403 guards on status endpoints
- src/lib/components/admin/Settings/General.svelte - Toggle UI
- src/lib/components/layout/Sidebar/UserMenu.svelte - Conditional status display
* Update UserMenu.svelte
feat: add ENABLE_USER_STATUS toggle for admin-controlled user status visibility
Add a new admin panel toggle (Admin > Settings > General) called "User Status" that allows administrators to globally enable or disable user status functionality.
When disabled:
- User status API endpoints return 403 Forbidden
- Active/Away indicator with blinking dot is hidden from the user menu
- Status emoji, message, and "Update your status" button are hidden from the user menu
The setting:
- Defaults to True (enabled)
- Can be overridden via ENABLE_USER_STATUS environment variable
- Persists across restarts using PersistentConfig
Files modified:
- backend/open_webui/config.py - Added ENABLE_USER_STATUS PersistentConfig
- backend/open_webui/main.py - App state init and features dict
- backend/open_webui/routers/auths.py - AdminConfig model and endpoints
- backend/open_webui/routers/users.py - 403 guards on status endpoints
- src/lib/components/admin/Settings/General.svelte - Toggle UI
- src/lib/components/layout/Sidebar/UserMenu.svelte - Conditional status display
* nuke the indicator
* fix
---
backend/open_webui/config.py | 6 ++++++
backend/open_webui/main.py | 3 +++
backend/open_webui/routers/auths.py | 4 ++++
backend/open_webui/routers/users.py | 12 ++++++++++++
src/lib/components/admin/Settings/General.svelte | 8 ++++++++
src/lib/components/layout/Sidebar.svelte | 8 ++++++--
src/lib/components/layout/Sidebar/UserMenu.svelte | 1 +
7 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py
index 3fee61f6e3..6a00c21c02 100644
--- a/backend/open_webui/config.py
+++ b/backend/open_webui/config.py
@@ -1574,6 +1574,12 @@ ENABLE_NOTES = PersistentConfig(
os.environ.get("ENABLE_NOTES", "True").lower() == "true",
)
+ENABLE_USER_STATUS = PersistentConfig(
+ "ENABLE_USER_STATUS",
+ "users.enable_status",
+ os.environ.get("ENABLE_USER_STATUS", "True").lower() == "true",
+)
+
ENABLE_EVALUATION_ARENA_MODELS = PersistentConfig(
"ENABLE_EVALUATION_ARENA_MODELS",
"evaluation.arena.enable",
diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py
index 2f384ee7d3..46a3350021 100644
--- a/backend/open_webui/main.py
+++ b/backend/open_webui/main.py
@@ -369,6 +369,7 @@ from open_webui.config import (
FOLDER_MAX_FILE_COUNT,
ENABLE_CHANNELS,
ENABLE_NOTES,
+ ENABLE_USER_STATUS,
ENABLE_COMMUNITY_SHARING,
ENABLE_MESSAGE_RATING,
ENABLE_USER_WEBHOOKS,
@@ -789,6 +790,7 @@ app.state.config.ENABLE_NOTES = ENABLE_NOTES
app.state.config.ENABLE_COMMUNITY_SHARING = ENABLE_COMMUNITY_SHARING
app.state.config.ENABLE_MESSAGE_RATING = ENABLE_MESSAGE_RATING
app.state.config.ENABLE_USER_WEBHOOKS = ENABLE_USER_WEBHOOKS
+app.state.config.ENABLE_USER_STATUS = ENABLE_USER_STATUS
app.state.config.ENABLE_EVALUATION_ARENA_MODELS = ENABLE_EVALUATION_ARENA_MODELS
app.state.config.EVALUATION_ARENA_MODELS = EVALUATION_ARENA_MODELS
@@ -1933,6 +1935,7 @@ async def get_app_config(request: Request):
"enable_community_sharing": app.state.config.ENABLE_COMMUNITY_SHARING,
"enable_message_rating": app.state.config.ENABLE_MESSAGE_RATING,
"enable_user_webhooks": app.state.config.ENABLE_USER_WEBHOOKS,
+ "enable_user_status": app.state.config.ENABLE_USER_STATUS,
"enable_admin_export": ENABLE_ADMIN_EXPORT,
"enable_admin_chat_access": ENABLE_ADMIN_CHAT_ACCESS,
"enable_google_drive_integration": app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION,
diff --git a/backend/open_webui/routers/auths.py b/backend/open_webui/routers/auths.py
index 2c6fc6108b..63032d71db 100644
--- a/backend/open_webui/routers/auths.py
+++ b/backend/open_webui/routers/auths.py
@@ -994,6 +994,7 @@ async def get_admin_config(request: Request, user=Depends(get_admin_user)):
"ENABLE_MEMORIES": request.app.state.config.ENABLE_MEMORIES,
"ENABLE_NOTES": request.app.state.config.ENABLE_NOTES,
"ENABLE_USER_WEBHOOKS": request.app.state.config.ENABLE_USER_WEBHOOKS,
+ "ENABLE_USER_STATUS": request.app.state.config.ENABLE_USER_STATUS,
"PENDING_USER_OVERLAY_TITLE": request.app.state.config.PENDING_USER_OVERLAY_TITLE,
"PENDING_USER_OVERLAY_CONTENT": request.app.state.config.PENDING_USER_OVERLAY_CONTENT,
"RESPONSE_WATERMARK": request.app.state.config.RESPONSE_WATERMARK,
@@ -1019,6 +1020,7 @@ class AdminConfig(BaseModel):
ENABLE_MEMORIES: bool
ENABLE_NOTES: bool
ENABLE_USER_WEBHOOKS: bool
+ ENABLE_USER_STATUS: bool
PENDING_USER_OVERLAY_TITLE: Optional[str] = None
PENDING_USER_OVERLAY_CONTENT: Optional[str] = None
RESPONSE_WATERMARK: Optional[str] = None
@@ -1068,6 +1070,7 @@ async def update_admin_config(
request.app.state.config.ENABLE_MESSAGE_RATING = form_data.ENABLE_MESSAGE_RATING
request.app.state.config.ENABLE_USER_WEBHOOKS = form_data.ENABLE_USER_WEBHOOKS
+ request.app.state.config.ENABLE_USER_STATUS = form_data.ENABLE_USER_STATUS
request.app.state.config.PENDING_USER_OVERLAY_TITLE = (
form_data.PENDING_USER_OVERLAY_TITLE
@@ -1097,6 +1100,7 @@ async def update_admin_config(
"ENABLE_MEMORIES": request.app.state.config.ENABLE_MEMORIES,
"ENABLE_NOTES": request.app.state.config.ENABLE_NOTES,
"ENABLE_USER_WEBHOOKS": request.app.state.config.ENABLE_USER_WEBHOOKS,
+ "ENABLE_USER_STATUS": request.app.state.config.ENABLE_USER_STATUS,
"PENDING_USER_OVERLAY_TITLE": request.app.state.config.PENDING_USER_OVERLAY_TITLE,
"PENDING_USER_OVERLAY_CONTENT": request.app.state.config.PENDING_USER_OVERLAY_CONTENT,
"RESPONSE_WATERMARK": request.app.state.config.RESPONSE_WATERMARK,
diff --git a/backend/open_webui/routers/users.py b/backend/open_webui/routers/users.py
index f10448458f..ac53b73c8b 100644
--- a/backend/open_webui/routers/users.py
+++ b/backend/open_webui/routers/users.py
@@ -333,8 +333,14 @@ async def update_user_settings_by_session_user(
@router.get("/user/status")
async def get_user_status_by_session_user(
+ request: Request,
user=Depends(get_verified_user), db: Session = Depends(get_session)
):
+ if not request.app.state.config.ENABLE_USER_STATUS:
+ raise HTTPException(
+ status_code=status.HTTP_403_FORBIDDEN,
+ detail=ERROR_MESSAGES.ACTION_PROHIBITED,
+ )
user = Users.get_user_by_id(user.id, db=db)
if user:
return user
@@ -352,10 +358,16 @@ async def get_user_status_by_session_user(
@router.post("/user/status/update")
async def update_user_status_by_session_user(
+ request: Request,
form_data: UserStatus,
user=Depends(get_verified_user),
db: Session = Depends(get_session),
):
+ if not request.app.state.config.ENABLE_USER_STATUS:
+ raise HTTPException(
+ status_code=status.HTTP_403_FORBIDDEN,
+ detail=ERROR_MESSAGES.ACTION_PROHIBITED,
+ )
user = Users.get_user_by_id(user.id, db=db)
if user:
user = Users.update_user_status_by_id(user.id, form_data, db=db)
diff --git a/src/lib/components/admin/Settings/General.svelte b/src/lib/components/admin/Settings/General.svelte
index c327937411..a739d852cb 100644
--- a/src/lib/components/admin/Settings/General.svelte
+++ b/src/lib/components/admin/Settings/General.svelte
@@ -757,6 +757,14 @@