feat(permissions): add reset to defaults button in permissions modals (#25931)

Adds a 'Reset to Defaults' button to both the Edit Default Permissions
modal and the Edit User Group permissions modal.

- Default permissions modal: resets to stock/env-var configuration
- User group modal: resets to current global default permissions

Backend: new GET /api/v1/users/default/permissions/defaults endpoint
that returns DEFAULT_USER_PERMISSIONS (env-var-based initial defaults).
This commit is contained in:
G30
2026-06-16 18:25:20 -04:00
committed by GitHub
parent 7ee75a0c04
commit 6b2d962cd6
3 changed files with 101 additions and 1 deletions

View File

@@ -269,6 +269,20 @@ async def update_default_user_permissions(request: Request, form_data: UserPermi
return request.app.state.config.USER_PERMISSIONS
@router.get('/default/permissions/defaults', response_model=UserPermissions)
async def get_default_user_permissions_defaults(user=Depends(get_admin_user)):
from open_webui.config import DEFAULT_USER_PERMISSIONS
return {
'workspace': WorkspacePermissions(**DEFAULT_USER_PERMISSIONS.get('workspace', {})),
'sharing': SharingPermissions(**DEFAULT_USER_PERMISSIONS.get('sharing', {})),
'access_grants': AccessGrantsPermissions(**DEFAULT_USER_PERMISSIONS.get('access_grants', {})),
'chat': ChatPermissions(**DEFAULT_USER_PERMISSIONS.get('chat', {})),
'features': FeaturesPermissions(**DEFAULT_USER_PERMISSIONS.get('features', {})),
'settings': SettingsPermissions(**DEFAULT_USER_PERMISSIONS.get('settings', {})),
}
############################
# GetUserSettingsBySessionUser
############################

View File

@@ -85,6 +85,33 @@ export const updateUserDefaultPermissions = async (token: string, permissions: o
return res;
};
export const getUserDefaultPermissionsDefaults = async (token: string) => {
let error = null;
const res = await fetch(`${WEBUI_API_BASE_URL}/users/default/permissions/defaults`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
}
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((err) => {
console.error(err);
error = err.detail;
return null;
});
if (error) {
throw error;
}
return res;
};
export const updateUserRole = async (token: string, id: string, role: string) => {
let error = null;

View File

@@ -10,9 +10,11 @@
import Users from './Users.svelte';
import GroupPreviewPanel from './GroupPreviewPanel.svelte';
import { DEFAULT_PERMISSIONS } from '$lib/constants/permissions';
import { getUserDefaultPermissions, getUserDefaultPermissionsDefaults } from '$lib/apis/users';
import UserPlusSolid from '$lib/components/icons/UserPlusSolid.svelte';
import WrenchSolid from '$lib/components/icons/WrenchSolid.svelte';
import ConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte';
import XMark from '$lib/components/icons/XMark.svelte';
export let onSubmit: Function = () => {};
@@ -31,6 +33,7 @@
let selectedTab = 'general';
let loading = false;
let showDeleteConfirmDialog = false;
let showResetConfirmDialog = false;
let userCount = 0;
@@ -56,6 +59,29 @@
show = false;
};
const resetToDefaultsHandler = async () => {
try {
// For user groups: reset to current global default permissions
// For default permissions modal: reset to stock/env-var configuration
const defaults = custom
? await getUserDefaultPermissions(localStorage.token)
: await getUserDefaultPermissionsDefaults(localStorage.token);
if (defaults) {
permissions = {
workspace: { ...DEFAULT_PERMISSIONS.workspace, ...defaults.workspace },
sharing: { ...DEFAULT_PERMISSIONS.sharing, ...defaults.sharing },
access_grants: { ...DEFAULT_PERMISSIONS.access_grants, ...defaults.access_grants },
chat: { ...DEFAULT_PERMISSIONS.chat, ...defaults.chat },
features: { ...DEFAULT_PERMISSIONS.features, ...defaults.features },
settings: { ...DEFAULT_PERMISSIONS.settings, ...defaults.settings }
};
toast.success($i18n.t('Permissions reset to defaults'));
}
} catch (error) {
toast.error(`${error}`);
}
};
const init = () => {
if (group) {
name = group.name;
@@ -94,6 +120,17 @@
}}
/>
<ConfirmDialog
bind:show={showResetConfirmDialog}
title={$i18n.t('Reset to Defaults')}
message={$i18n.t(
'Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.'
)}
on:confirm={() => {
resetToDefaultsHandler();
}}
/>
<Modal size="lg" bind:show>
<div>
<div class=" flex justify-between dark:text-gray-100 px-5 pt-4 mb-1.5">
@@ -250,7 +287,29 @@
</div>
{#if ['general', 'permissions'].includes(selectedTab)}
<div class="flex justify-end pt-3 text-sm font-medium gap-1.5">
<div class="flex justify-between items-center pt-3 text-sm font-medium gap-1.5">
<div>
{#if selectedTab === 'permissions'}
<Tooltip
content={custom
? $i18n.t(
'Reset group permissions to match the current default user permissions'
)
: $i18n.t('Reset all permissions to their initial configuration values')}
>
<button
class="text-sm font-normal text-gray-500 hover:text-gray-700 dark:text-gray-500 dark:hover:text-gray-300 transition hover:underline"
type="button"
on:click={() => {
showResetConfirmDialog = true;
}}
>
{$i18n.t('Reset to Defaults')}
</button>
</Tooltip>
{/if}
</div>
<button
class="px-3.5 py-1.5 text-sm font-medium bg-black hover:bg-gray-900 text-white dark:bg-white dark:text-black dark:hover:bg-gray-100 transition rounded-full flex items-center gap-2 whitespace-nowrap {loading
? ' cursor-not-allowed'