mirror of
https://github.com/inventree/InvenTree.git
synced 2026-04-14 15:28:52 +00:00
[UI] Adjust "superuser warning" banner (#11696)
* Fix typo - evelevated -> elevated * Add playwright test * Add new control settings
This commit is contained in:
@@ -27,6 +27,8 @@ Configuration of basic server settings:
|
|||||||
{{ globalsetting("INVENTREE_INSTANCE_TITLE") }}
|
{{ globalsetting("INVENTREE_INSTANCE_TITLE") }}
|
||||||
{{ globalsetting("INVENTREE_INSTANCE_ID", default="Randomly generated value") }}
|
{{ globalsetting("INVENTREE_INSTANCE_ID", default="Randomly generated value") }}
|
||||||
{{ globalsetting("INVENTREE_ANNOUNCE_ID") }}
|
{{ globalsetting("INVENTREE_ANNOUNCE_ID") }}
|
||||||
|
{{ globalsetting("INVENTREE_SHOW_SUPERUSER_BANNER") }}
|
||||||
|
{{ globalsetting("INVENTREE_SHOW_ADMIN_BANNER") }}
|
||||||
{{ globalsetting("INVENTREE_RESTRICT_ABOUT") }}
|
{{ globalsetting("INVENTREE_RESTRICT_ABOUT") }}
|
||||||
{{ globalsetting("DISPLAY_FULL_NAMES") }}
|
{{ globalsetting("DISPLAY_FULL_NAMES") }}
|
||||||
{{ globalsetting("DISPLAY_PROFILE_INFO") }}
|
{{ globalsetting("DISPLAY_PROFILE_INFO") }}
|
||||||
|
|||||||
@@ -535,7 +535,6 @@ Set the `INVENTREE_FRONTEND_SETTINGS` Environment variable to a JSON object or u
|
|||||||
| `url_compatibility` | Support compatibility with "legacy" URLs? | `true` |
|
| `url_compatibility` | Support compatibility with "legacy" URLs? | `true` |
|
||||||
| `sentry_dsn` | Set a Sentry DSN url | *Not specified* |
|
| `sentry_dsn` | Set a Sentry DSN url | *Not specified* |
|
||||||
| `mobile_mode` | Controls if InvenTree web UI can be used by mobile devices. There are 3 options: `default` - does not allow mobile devices; `allow-ignore` - shows a mobile device detected banner with a button to ignore this warning AT THE USERS OWN RISK; `allow-always` - skips the mobile check and allows mobile devices always (of course at the server admins OWN RISK) | `default` |
|
| `mobile_mode` | Controls if InvenTree web UI can be used by mobile devices. There are 3 options: `default` - does not allow mobile devices; `allow-ignore` - shows a mobile device detected banner with a button to ignore this warning AT THE USERS OWN RISK; `allow-always` - skips the mobile check and allows mobile devices always (of course at the server admins OWN RISK) | `default` |
|
||||||
| `dangerous_hide_evelevated_alert` | Hides the elevated permissions alert in the UI. This is a dangerous option as using the UI with elevated permissions is against the threat model. | `false` |
|
|
||||||
|
|
||||||
E.g. to allow mobile devices to ignore the mobile check, use the following Environment variable:
|
E.g. to allow mobile devices to ignore the mobile check, use the following Environment variable:
|
||||||
|
|
||||||
|
|||||||
@@ -235,6 +235,18 @@ SYSTEM_SETTINGS: dict[str, InvenTreeSettingsKeyType] = {
|
|||||||
'validator': bool,
|
'validator': bool,
|
||||||
'default': False,
|
'default': False,
|
||||||
},
|
},
|
||||||
|
'INVENTREE_SHOW_SUPERUSER_BANNER': {
|
||||||
|
'name': _('Show superuser banner'),
|
||||||
|
'description': _('Show a warning banner in the UI when logged in as superuser'),
|
||||||
|
'validator': bool,
|
||||||
|
'default': True,
|
||||||
|
},
|
||||||
|
'INVENTREE_SHOW_ADMIN_BANNER': {
|
||||||
|
'name': _('Show admin banner'),
|
||||||
|
'description': _('Show a warning banner in the UI when logged in as admin'),
|
||||||
|
'validator': bool,
|
||||||
|
'default': False,
|
||||||
|
},
|
||||||
'INVENTREE_COMPANY_NAME': {
|
'INVENTREE_COMPANY_NAME': {
|
||||||
'name': _('Company name'),
|
'name': _('Company name'),
|
||||||
'description': _('Internal company name'),
|
'description': _('Internal company name'),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
Container,
|
Container,
|
||||||
Group,
|
Group,
|
||||||
Indicator,
|
Indicator,
|
||||||
|
Paper,
|
||||||
Tabs,
|
Tabs,
|
||||||
Text,
|
Text,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
@@ -14,7 +15,7 @@ import {
|
|||||||
useDocumentVisibility,
|
useDocumentVisibility,
|
||||||
useHotkeys
|
useHotkeys
|
||||||
} from '@mantine/hooks';
|
} from '@mantine/hooks';
|
||||||
import { IconBell, IconSearch } from '@tabler/icons-react';
|
import { IconBell, IconSearch, IconUserBolt } from '@tabler/icons-react';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { type ReactNode, useEffect, useMemo, useState } from 'react';
|
import { type ReactNode, useEffect, useMemo, useState } from 'react';
|
||||||
import { useMatch, useNavigate } from 'react-router-dom';
|
import { useMatch, useNavigate } from 'react-router-dom';
|
||||||
@@ -58,8 +59,6 @@ export function Header() {
|
|||||||
searchDrawerOpened,
|
searchDrawerOpened,
|
||||||
{ open: openSearchDrawer, close: closeSearchDrawer }
|
{ open: openSearchDrawer, close: closeSearchDrawer }
|
||||||
] = useDisclosure(false);
|
] = useDisclosure(false);
|
||||||
const [elevatedAlertClosed, setElevatedAlertClosed] =
|
|
||||||
useState<boolean>(false);
|
|
||||||
|
|
||||||
useHotkeys([
|
useHotkeys([
|
||||||
[
|
[
|
||||||
@@ -130,13 +129,25 @@ export function Header() {
|
|||||||
else closeNavDrawer();
|
else closeNavDrawer();
|
||||||
}, [navigationOpen]);
|
}, [navigationOpen]);
|
||||||
|
|
||||||
const showElevated = useMemo(
|
const [showSuperuserAlert, setShowSuperuserAlert] = useState<boolean>(true);
|
||||||
() =>
|
|
||||||
(user?.is_staff || user?.is_superuser || false) &&
|
const showElevated = useMemo(() => {
|
||||||
!elevatedAlertClosed &&
|
if (
|
||||||
!window.INVENTREE_SETTINGS.dangerous_hide_evelevated_alert,
|
user?.is_superuser &&
|
||||||
[user, elevatedAlertClosed]
|
globalSettings.isSet('INVENTREE_SHOW_SUPERUSER_BANNER', true)
|
||||||
);
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
user?.is_staff &&
|
||||||
|
globalSettings.isSet('INVENTREE_SHOW_ADMIN_BANNER', true)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}, [user, showSuperuserAlert, globalSettings]);
|
||||||
|
|
||||||
const headerStyle: any = useMemo(() => {
|
const headerStyle: any = useMemo(() => {
|
||||||
const sticky: boolean = userSettings.isSet('STICKY_HEADER', true);
|
const sticky: boolean = userSettings.isSet('STICKY_HEADER', true);
|
||||||
@@ -210,18 +221,22 @@ export function Header() {
|
|||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</Container>
|
</Container>
|
||||||
{showElevated && user && (
|
{showElevated && (user?.is_superuser || user?.is_staff) && (
|
||||||
<Alert
|
<Paper p={0} m={5}>
|
||||||
color={user.is_superuser ? 'red' : 'orange'}
|
<Alert
|
||||||
title={user.is_superuser ? t`Superuser Mode` : t`Administrator Mode`}
|
icon={<IconUserBolt />}
|
||||||
withCloseButton
|
color={user.is_superuser ? 'red' : 'orange'}
|
||||||
onClose={() => setElevatedAlertClosed(true)}
|
title={user.is_superuser ? t`Superuser Mode` : t`Admin Mode`}
|
||||||
>
|
withCloseButton
|
||||||
<Text>
|
onClose={() => setShowSuperuserAlert(false)}
|
||||||
{t`The current user has elevated privileges and should not be used for regular usage.`}
|
p={5}
|
||||||
{errorCodeLink('INVE-W14')}
|
>
|
||||||
</Text>
|
<Text p={0}>
|
||||||
</Alert>
|
{t`The current user has elevated privileges and should not be used for regular usage.`}{' '}
|
||||||
|
{errorCodeLink('INVE-W14')}
|
||||||
|
</Text>
|
||||||
|
</Alert>
|
||||||
|
</Paper>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ declare global {
|
|||||||
sentry_dsn?: string;
|
sentry_dsn?: string;
|
||||||
environment?: string;
|
environment?: string;
|
||||||
mobile_mode?: 'default' | 'allow-ignore' | 'allow-always';
|
mobile_mode?: 'default' | 'allow-ignore' | 'allow-always';
|
||||||
dangerous_hide_evelevated_alert?: boolean;
|
|
||||||
};
|
};
|
||||||
react: typeof React;
|
react: typeof React;
|
||||||
React: typeof React;
|
React: typeof React;
|
||||||
|
|||||||
@@ -50,10 +50,12 @@ export default function SystemSettings() {
|
|||||||
keys={[
|
keys={[
|
||||||
'INVENTREE_BASE_URL',
|
'INVENTREE_BASE_URL',
|
||||||
'INVENTREE_COMPANY_NAME',
|
'INVENTREE_COMPANY_NAME',
|
||||||
'INVENTREE_INSTANCE_ID',
|
|
||||||
'INVENTREE_ANNOUNCE_ID',
|
|
||||||
'INVENTREE_INSTANCE',
|
'INVENTREE_INSTANCE',
|
||||||
'INVENTREE_INSTANCE_TITLE',
|
'INVENTREE_INSTANCE_TITLE',
|
||||||
|
'INVENTREE_INSTANCE_ID',
|
||||||
|
'INVENTREE_ANNOUNCE_ID',
|
||||||
|
'INVENTREE_SHOW_SUPERUSER_BANNER',
|
||||||
|
'INVENTREE_SHOW_ADMIN_BANNER',
|
||||||
'INVENTREE_RESTRICT_ABOUT',
|
'INVENTREE_RESTRICT_ABOUT',
|
||||||
'DISPLAY_FULL_NAMES',
|
'DISPLAY_FULL_NAMES',
|
||||||
'DISPLAY_PROFILE_INFO',
|
'DISPLAY_PROFILE_INFO',
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ test('Permissions - Admin', async ({ browser }) => {
|
|||||||
url: '/settings/admin/'
|
url: '/settings/admin/'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Check for superuser banner
|
||||||
|
await page.getByText('Superuser Mode').waitFor();
|
||||||
|
await page.getByText('The current user has elevated').waitFor();
|
||||||
|
|
||||||
// Check for expected tabs
|
// Check for expected tabs
|
||||||
await loadTab(page, 'Machines');
|
await loadTab(page, 'Machines');
|
||||||
await loadTab(page, 'Plugins');
|
await loadTab(page, 'Plugins');
|
||||||
|
|||||||
Reference in New Issue
Block a user