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:
3 files changed
+101
-1
No files matched your search
@@ -269,6 +269,20 @@ async def update_default_user_permissions(request: Request, form_data: UserPermi
|
|||||||
return request.app.state.config.USER_PERMISSIONS
|
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
|
# GetUserSettingsBySessionUser
|
||||||
############################
|
############################
|
||||||
|
|||||||
@@ -85,6 +85,33 @@ export const updateUserDefaultPermissions = async (token: string, permissions: o
|
|||||||
return res;
|
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) => {
|
export const updateUserRole = async (token: string, id: string, role: string) => {
|
||||||
let error = null;
|
let error = null;
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,11 @@
|
|||||||
import Users from './Users.svelte';
|
import Users from './Users.svelte';
|
||||||
import GroupPreviewPanel from './GroupPreviewPanel.svelte';
|
import GroupPreviewPanel from './GroupPreviewPanel.svelte';
|
||||||
import { DEFAULT_PERMISSIONS } from '$lib/constants/permissions';
|
import { DEFAULT_PERMISSIONS } from '$lib/constants/permissions';
|
||||||
|
import { getUserDefaultPermissions, getUserDefaultPermissionsDefaults } from '$lib/apis/users';
|
||||||
import UserPlusSolid from '$lib/components/icons/UserPlusSolid.svelte';
|
import UserPlusSolid from '$lib/components/icons/UserPlusSolid.svelte';
|
||||||
import WrenchSolid from '$lib/components/icons/WrenchSolid.svelte';
|
import WrenchSolid from '$lib/components/icons/WrenchSolid.svelte';
|
||||||
import ConfirmDialog from '$lib/components/common/ConfirmDialog.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';
|
import XMark from '$lib/components/icons/XMark.svelte';
|
||||||
|
|
||||||
export let onSubmit: Function = () => {};
|
export let onSubmit: Function = () => {};
|
||||||
@@ -31,6 +33,7 @@
|
|||||||
let selectedTab = 'general';
|
let selectedTab = 'general';
|
||||||
let loading = false;
|
let loading = false;
|
||||||
let showDeleteConfirmDialog = false;
|
let showDeleteConfirmDialog = false;
|
||||||
|
let showResetConfirmDialog = false;
|
||||||
|
|
||||||
let userCount = 0;
|
let userCount = 0;
|
||||||
|
|
||||||
@@ -56,6 +59,29 @@
|
|||||||
show = false;
|
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 = () => {
|
const init = () => {
|
||||||
if (group) {
|
if (group) {
|
||||||
name = group.name;
|
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>
|
<Modal size="lg" bind:show>
|
||||||
<div>
|
<div>
|
||||||
<div class=" flex justify-between dark:text-gray-100 px-5 pt-4 mb-1.5">
|
<div class=" flex justify-between dark:text-gray-100 px-5 pt-4 mb-1.5">
|
||||||
@@ -250,7 +287,29 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if ['general', 'permissions'].includes(selectedTab)}
|
{#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
|
<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
|
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'
|
? ' cursor-not-allowed'
|
||||||
|
|||||||
Reference in new issue
Block a user