feat: Add default group assignment for new users (#94) (#19325)

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Classic298 2025-11-20 23:47:15 +01:00 committed by GitHub
parent 680cde8f9b
commit b65c728208
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 40 additions and 2 deletions

View file

@ -1203,6 +1203,12 @@ DEFAULT_USER_ROLE = PersistentConfig(
os.getenv("DEFAULT_USER_ROLE", "pending"), os.getenv("DEFAULT_USER_ROLE", "pending"),
) )
DEFAULT_GROUP_ID = PersistentConfig(
"DEFAULT_GROUP_ID",
"ui.default_group_id",
os.environ.get("DEFAULT_GROUP_ID", ""),
)
PENDING_USER_OVERLAY_TITLE = PersistentConfig( PENDING_USER_OVERLAY_TITLE = PersistentConfig(
"PENDING_USER_OVERLAY_TITLE", "PENDING_USER_OVERLAY_TITLE",
"ui.pending_user_overlay_title", "ui.pending_user_overlay_title",

View file

@ -369,6 +369,7 @@ from open_webui.config import (
BYPASS_ADMIN_ACCESS_CONTROL, BYPASS_ADMIN_ACCESS_CONTROL,
USER_PERMISSIONS, USER_PERMISSIONS,
DEFAULT_USER_ROLE, DEFAULT_USER_ROLE,
DEFAULT_GROUP_ID,
PENDING_USER_OVERLAY_CONTENT, PENDING_USER_OVERLAY_CONTENT,
PENDING_USER_OVERLAY_TITLE, PENDING_USER_OVERLAY_TITLE,
DEFAULT_PROMPT_SUGGESTIONS, DEFAULT_PROMPT_SUGGESTIONS,
@ -762,6 +763,7 @@ app.state.config.MODEL_ORDER_LIST = MODEL_ORDER_LIST
app.state.config.DEFAULT_PROMPT_SUGGESTIONS = DEFAULT_PROMPT_SUGGESTIONS app.state.config.DEFAULT_PROMPT_SUGGESTIONS = DEFAULT_PROMPT_SUGGESTIONS
app.state.config.DEFAULT_USER_ROLE = DEFAULT_USER_ROLE app.state.config.DEFAULT_USER_ROLE = DEFAULT_USER_ROLE
app.state.config.DEFAULT_GROUP_ID = DEFAULT_GROUP_ID
app.state.config.PENDING_USER_OVERLAY_CONTENT = PENDING_USER_OVERLAY_CONTENT app.state.config.PENDING_USER_OVERLAY_CONTENT = PENDING_USER_OVERLAY_CONTENT
app.state.config.PENDING_USER_OVERLAY_TITLE = PENDING_USER_OVERLAY_TITLE app.state.config.PENDING_USER_OVERLAY_TITLE = PENDING_USER_OVERLAY_TITLE

View file

@ -694,7 +694,11 @@ async def signup(request: Request, response: Response, form_data: SignupForm):
if not has_users: if not has_users:
# Disable signup after the first user is created # Disable signup after the first user is created
request.app.state.config.ENABLE_SIGNUP = False request.app.state.config.ENABLE_SIGNUP = False
default_group_id = getattr(request.app.state.config, 'DEFAULT_GROUP_ID', "")
if default_group_id and default_group_id:
Groups.add_users_to_group(default_group_id, [user.id])
return { return {
"token": token, "token": token,
"token_type": "Bearer", "token_type": "Bearer",
@ -888,6 +892,7 @@ async def get_admin_config(request: Request, user=Depends(get_admin_user)):
"ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS": request.app.state.config.ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS, "ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS": request.app.state.config.ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS,
"API_KEYS_ALLOWED_ENDPOINTS": request.app.state.config.API_KEYS_ALLOWED_ENDPOINTS, "API_KEYS_ALLOWED_ENDPOINTS": request.app.state.config.API_KEYS_ALLOWED_ENDPOINTS,
"DEFAULT_USER_ROLE": request.app.state.config.DEFAULT_USER_ROLE, "DEFAULT_USER_ROLE": request.app.state.config.DEFAULT_USER_ROLE,
"DEFAULT_GROUP_ID": request.app.state.config.DEFAULT_GROUP_ID,
"JWT_EXPIRES_IN": request.app.state.config.JWT_EXPIRES_IN, "JWT_EXPIRES_IN": request.app.state.config.JWT_EXPIRES_IN,
"ENABLE_COMMUNITY_SHARING": request.app.state.config.ENABLE_COMMUNITY_SHARING, "ENABLE_COMMUNITY_SHARING": request.app.state.config.ENABLE_COMMUNITY_SHARING,
"ENABLE_MESSAGE_RATING": request.app.state.config.ENABLE_MESSAGE_RATING, "ENABLE_MESSAGE_RATING": request.app.state.config.ENABLE_MESSAGE_RATING,
@ -908,6 +913,7 @@ class AdminConfig(BaseModel):
ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS: bool ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS: bool
API_KEYS_ALLOWED_ENDPOINTS: str API_KEYS_ALLOWED_ENDPOINTS: str
DEFAULT_USER_ROLE: str DEFAULT_USER_ROLE: str
DEFAULT_GROUP_ID: str
JWT_EXPIRES_IN: str JWT_EXPIRES_IN: str
ENABLE_COMMUNITY_SHARING: bool ENABLE_COMMUNITY_SHARING: bool
ENABLE_MESSAGE_RATING: bool ENABLE_MESSAGE_RATING: bool
@ -922,7 +928,7 @@ class AdminConfig(BaseModel):
@router.post("/admin/config") @router.post("/admin/config")
async def update_admin_config( async def update_admin_config(
request: Request, form_data: AdminConfig, user=Depends(get_admin_user) request: Request, form_data: AdminConfig, user=Depends(get_admin_user)
): ):
request.app.state.config.SHOW_ADMIN_DETAILS = form_data.SHOW_ADMIN_DETAILS request.app.state.config.SHOW_ADMIN_DETAILS = form_data.SHOW_ADMIN_DETAILS
request.app.state.config.WEBUI_URL = form_data.WEBUI_URL request.app.state.config.WEBUI_URL = form_data.WEBUI_URL
request.app.state.config.ENABLE_SIGNUP = form_data.ENABLE_SIGNUP request.app.state.config.ENABLE_SIGNUP = form_data.ENABLE_SIGNUP
@ -941,6 +947,8 @@ async def update_admin_config(
if form_data.DEFAULT_USER_ROLE in ["pending", "user", "admin"]: if form_data.DEFAULT_USER_ROLE in ["pending", "user", "admin"]:
request.app.state.config.DEFAULT_USER_ROLE = form_data.DEFAULT_USER_ROLE request.app.state.config.DEFAULT_USER_ROLE = form_data.DEFAULT_USER_ROLE
request.app.state.config.DEFAULT_GROUP_ID = form_data.DEFAULT_GROUP_ID
pattern = r"^(-1|0|(-?\d+(\.\d+)?)(ms|s|m|h|d|w))$" pattern = r"^(-1|0|(-?\d+(\.\d+)?)(ms|s|m|h|d|w))$"
# Check if the input string matches the pattern # Check if the input string matches the pattern
@ -971,6 +979,7 @@ async def update_admin_config(
"ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS": request.app.state.config.ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS, "ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS": request.app.state.config.ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS,
"API_KEYS_ALLOWED_ENDPOINTS": request.app.state.config.API_KEYS_ALLOWED_ENDPOINTS, "API_KEYS_ALLOWED_ENDPOINTS": request.app.state.config.API_KEYS_ALLOWED_ENDPOINTS,
"DEFAULT_USER_ROLE": request.app.state.config.DEFAULT_USER_ROLE, "DEFAULT_USER_ROLE": request.app.state.config.DEFAULT_USER_ROLE,
"DEFAULT_GROUP_ID": request.app.state.config.DEFAULT_GROUP_ID,
"JWT_EXPIRES_IN": request.app.state.config.JWT_EXPIRES_IN, "JWT_EXPIRES_IN": request.app.state.config.JWT_EXPIRES_IN,
"ENABLE_COMMUNITY_SHARING": request.app.state.config.ENABLE_COMMUNITY_SHARING, "ENABLE_COMMUNITY_SHARING": request.app.state.config.ENABLE_COMMUNITY_SHARING,
"ENABLE_MESSAGE_RATING": request.app.state.config.ENABLE_MESSAGE_RATING, "ENABLE_MESSAGE_RATING": request.app.state.config.ENABLE_MESSAGE_RATING,

View file

@ -10,6 +10,7 @@
updateLdapConfig, updateLdapConfig,
updateLdapServer updateLdapServer
} from '$lib/apis/auths'; } from '$lib/apis/auths';
import { getGroups } from '$lib/apis/groups';
import SensitiveInput from '$lib/components/common/SensitiveInput.svelte'; import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
import Switch from '$lib/components/common/Switch.svelte'; import Switch from '$lib/components/common/Switch.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte'; import Tooltip from '$lib/components/common/Tooltip.svelte';
@ -32,6 +33,7 @@
let adminConfig = null; let adminConfig = null;
let webhookUrl = ''; let webhookUrl = '';
let groups = [];
// LDAP // LDAP
let ENABLE_LDAP = false; let ENABLE_LDAP = false;
@ -104,6 +106,9 @@
})(), })(),
(async () => { (async () => {
LDAP_SERVER = await getLdapServer(localStorage.token); LDAP_SERVER = await getLdapServer(localStorage.token);
})(),
(async () => {
groups = await getGroups(localStorage.token);
})() })()
]); ]);
@ -299,6 +304,22 @@
</div> </div>
</div> </div>
<div class=" mb-2.5 flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('Default Group')}</div>
<div class="flex items-center relative">
<select
class="dark:bg-gray-900 w-fit pr-8 rounded-sm px-2 text-xs bg-transparent outline-hidden text-right"
bind:value={adminConfig.DEFAULT_GROUP_ID}
placeholder={$i18n.t('Select a group')}
>
<option value={""}>None</option>
{#each groups as group}
<option value={group.id}>{group.name}</option>
{/each}
</select>
</div>
</div>
<div class=" mb-2.5 flex w-full justify-between pr-2"> <div class=" mb-2.5 flex w-full justify-between pr-2">
<div class=" self-center text-xs font-medium">{$i18n.t('Enable New Sign Ups')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('Enable New Sign Ups')}</div>