* 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
Replaced per-message user lookup with batch fetch using SQL IN clause.
Changes:
- Fetch all message user_ids in a single pass
- Use Users.get_users_by_user_ids() for batch lookup
- Build user mapping to avoid DB calls in loop
- Add early return for empty message lists
Performance: Reduces N+1 queries to 2 queries (messages + users)
Replaced per-message user lookup with batch fetch using SQL IN clause.
Changes:
- Fetch all message user_ids in a single pass
- Use Users.get_users_by_user_ids() for batch lookup
- Build user mapping to avoid DB calls in loop
- Add early return for empty message lists
Performance: Reduces N+1 queries to 2 queries (messages + users)
## Summary
Fixed N+1 query pattern in the `/api/v1/users` endpoint where groups were being fetched for each user individually.
### Problem
The `GET /api/v1/users` endpoint called `Groups.get_groups_by_member_id()` for each user, resulting in:
- 1 query for users
- N queries for groups (one per user)
### Solution
Added a new `Groups.get_groups_by_member_ids()` method that fetches groups for multiple users in a single query using SQL `IN` clause and `JOIN`.
### Changes
- **[groups.py](open_webui/models/groups.py)**: Added `get_groups_by_member_ids()` method
- **[users.py](open_webui/routers/users.py)**: Updated endpoint to use bulk method
### Result
- Before: 1 + N queries
- After: 2 queries total (1 for users, 1 for all groups)
* feat: Add read-only access support for Tools
- Backend: Add write_access field to ToolAccessResponse
- Backend: Update /tools/list to return tools with write_access
- Frontend: Display Read Only badge in Tools list
- Frontend: Disable inputs and save button when no write access
- Frontend: Add readOnly prop to CodeEditor component
* Update Tools.svelte
* fix: Return write_access from getToolById endpoint
fix: Return write_access from getToolById endpoint
- Use ToolAccessResponse instead of raw dict
- Remove inefficient getToolList call in edit page
* refactor: Rename write_access to disabled in ToolkitEditor
- Rename prop from write_access to disabled
- Invert logic where needed
- Update edit page to pass disabled instead of write_access
* rem
* Update +page.svelte
* fix
* Update ToolkitEditor.svelte
* Update CodeEditor.svelte
* Update ToolkitEditor.svelte
* feat: Add read-only access support for Models
- Backend: Add write_access field to ModelAccessResponse
- Backend: Update /models/list to return ModelAccessListResponse
- Frontend: Display Read Only badge in Models list
- Frontend: Disable inputs and save button when no write access
- Frontend: Hide action buttons for read-only models
* fix: Handle ModelAccessListResponse format in getModels API
- Backend returns {items, total} instead of {data}
- Update getModels API to handle both formats for backward compatibility
* fix: Show read-only shared models in workspace list
- Backend: Change search_models permission from 'write' to 'read' to include shared models
- Backend: Keep user_id filter to only show owned/shared models (not all public)
- Frontend: Handle ModelAccessListResponse format in getModels API
* fix: Align Read Only badge inline with model name
* fix: Correct badge placement and fix syntax error
* fix: Resolve badge truncation in Models list
- Add w-full to flex container for proper spacing
- Wrap Badge in div to prevent truncation
- Match Knowledge.svelte badge pattern
* fix: Align Read Only badge with Knowledge.svelte pattern
- Match Knowledge.svelte structure for badge placement
- Actions only show when write_access or admin
- Remove w-full from container to prevent right-overflow
* fix: Return write_access from getModelById endpoint
fix: Return write_access from getModelById endpoint
- Use ModelAccessResponse instead of raw dict
- Remove inefficient getModels call in edit page
* revert
* fix
* fix
* fix