diff --git a/apps/meteor/client/components/ABAC/ABACUpsellModal/ABACUpsellModal.spec.tsx b/apps/meteor/client/components/ABAC/ABACUpsellModal/ABACUpsellModal.spec.tsx
index c2fd14fb4feb9..584b64aece7fb 100644
--- a/apps/meteor/client/components/ABAC/ABACUpsellModal/ABACUpsellModal.spec.tsx
+++ b/apps/meteor/client/components/ABAC/ABACUpsellModal/ABACUpsellModal.spec.tsx
@@ -4,11 +4,7 @@ import userEvent from '@testing-library/user-event';
import { axe } from 'jest-axe';
import ABACUpsellModal from './ABACUpsellModal';
-
-// Mock the hooks used by ABACUpsellModal
-jest.mock('../../../hooks/useHasLicenseModule', () => ({
- useHasLicenseModule: jest.fn(() => false),
-}));
+import { createFakeLicenseInfo } from '../../../../tests/mocks/data';
jest.mock('../../GenericUpsellModal/hooks', () => ({
useUpsellActions: jest.fn(() => ({
@@ -34,6 +30,9 @@ const appRoot = mockAppRoot()
Upgrade: 'Upgrade',
Cancel: 'Cancel',
})
+ .withEndpoint('GET', '/v1/licenses.info', async () => ({
+ license: createFakeLicenseInfo(),
+ }))
.build();
describe('ABACUpsellModal', () => {
diff --git a/apps/meteor/client/lib/links.ts b/apps/meteor/client/lib/links.ts
index 4c97d4696fff5..a1e28ddc853d3 100644
--- a/apps/meteor/client/lib/links.ts
+++ b/apps/meteor/client/lib/links.ts
@@ -31,6 +31,10 @@ export const links = {
trial: `${GO_ROCKET_CHAT_PREFIX}/i/docs-trial`,
versionSupport: `${GO_ROCKET_CHAT_PREFIX}/i/version-support`,
updateProduct: `${GO_ROCKET_CHAT_PREFIX}/i/update-product`,
+ // TODO: implement abac links when available
+ abacDocs: `${GO_ROCKET_CHAT_PREFIX}/i/TODO-ABAC-DOCS`,
+ abacLicenseRenewalUrl: `${GO_ROCKET_CHAT_PREFIX}/i/TODO-ABAC-LICENSE-RENEWAL-URL`,
+ abacLDAPDocs: `${GO_ROCKET_CHAT_PREFIX}/i/TODO-ABAC-LDAP-DOCS`,
},
/** @deprecated use `go.rocket.chat` links */
desktopAppDownload: 'https://rocket.chat/download',
diff --git a/apps/meteor/client/views/admin/ABAC/AdminABACPage.tsx b/apps/meteor/client/views/admin/ABAC/AdminABACPage.tsx
new file mode 100644
index 0000000000000..d8352181e4df9
--- /dev/null
+++ b/apps/meteor/client/views/admin/ABAC/AdminABACPage.tsx
@@ -0,0 +1,47 @@
+import { Box, Button, Callout } from '@rocket.chat/fuselage';
+import { useRouteParameter } from '@rocket.chat/ui-contexts';
+import { Trans, useTranslation } from 'react-i18next';
+
+import AdminABACSettings from './AdminABACSettings';
+import AdminABACTabs from './AdminABACTabs';
+import { Page, PageContent, PageHeader } from '../../../components/Page';
+import { useExternalLink } from '../../../hooks/useExternalLink';
+import { links } from '../../../lib/links';
+
+type AdminABACPageProps = {
+ shouldShowWarning: boolean;
+};
+
+const AdminABACPage = ({ shouldShowWarning }: AdminABACPageProps) => {
+ const { t } = useTranslation();
+ const tab = useRouteParameter('tab');
+ const learnMore = useExternalLink();
+
+ return (
+
+
+
+
+
+ {shouldShowWarning && (
+
+
+
+ Renew your license to continue using all{' '}
+
+ ABAC capabilities without restriction.
+
+
+
+
+ )}
+
+ {tab === 'settings' && }
+
+
+ );
+};
+
+export default AdminABACPage;
diff --git a/apps/meteor/client/views/admin/ABAC/AdminABACRoute.tsx b/apps/meteor/client/views/admin/ABAC/AdminABACRoute.tsx
new file mode 100644
index 0000000000000..20a1db6239b81
--- /dev/null
+++ b/apps/meteor/client/views/admin/ABAC/AdminABACRoute.tsx
@@ -0,0 +1,64 @@
+import { usePermission, useSetModal, useCurrentModal, useRouter, useRouteParameter, useSettingStructure } from '@rocket.chat/ui-contexts';
+import type { ReactElement } from 'react';
+import { memo, useEffect, useLayoutEffect } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import AdminABACPage from './AdminABACPage';
+import ABACUpsellModal from '../../../components/ABAC/ABACUpsellModal/ABACUpsellModal';
+import { useUpsellActions } from '../../../components/GenericUpsellModal/hooks';
+import PageSkeleton from '../../../components/PageSkeleton';
+import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule';
+import SettingsProvider from '../../../providers/SettingsProvider';
+import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage';
+import EditableSettingsProvider from '../settings/EditableSettingsProvider';
+
+const AdminABACRoute = (): ReactElement => {
+ const { t } = useTranslation();
+ // TODO: Check what permission is needed to view the ABAC page
+ const canViewABACPage = usePermission('abac-management');
+ const hasABAC = useHasLicenseModule('abac') === true;
+ const isModalOpen = !!useCurrentModal();
+ const tab = useRouteParameter('tab');
+ const router = useRouter();
+
+ // Check if setting exists in the DB to decide if we show warning or upsell
+ const ABACEnabledSetting = useSettingStructure('ABAC_Enabled');
+
+ useLayoutEffect(() => {
+ if (!tab) {
+ router.navigate({
+ name: 'admin-ABAC',
+ params: { tab: 'settings' },
+ });
+ }
+ }, [tab, router]);
+
+ const { shouldShowUpsell, handleManageSubscription } = useUpsellActions(hasABAC);
+
+ const setModal = useSetModal();
+
+ useEffect(() => {
+ // WS has never activated ABAC
+ if (shouldShowUpsell && ABACEnabledSetting === undefined) {
+ setModal( setModal(null)} onConfirm={handleManageSubscription} />);
+ }
+ }, [shouldShowUpsell, setModal, t, handleManageSubscription, ABACEnabledSetting]);
+
+ if (isModalOpen) {
+ return ;
+ }
+
+ if (!canViewABACPage || (ABACEnabledSetting === undefined && !hasABAC)) {
+ return ;
+ }
+
+ return (
+
+
+
+
+
+ );
+};
+
+export default memo(AdminABACRoute);
diff --git a/apps/meteor/client/views/admin/ABAC/AdminABACSettingToggle.spec.tsx b/apps/meteor/client/views/admin/ABAC/AdminABACSettingToggle.spec.tsx
new file mode 100644
index 0000000000000..f235bce08db84
--- /dev/null
+++ b/apps/meteor/client/views/admin/ABAC/AdminABACSettingToggle.spec.tsx
@@ -0,0 +1,142 @@
+import type { ISetting } from '@rocket.chat/apps-engine/definition/settings';
+import { mockAppRoot } from '@rocket.chat/mock-providers';
+import { render, screen, waitFor } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import { axe } from 'jest-axe';
+
+import AdminABACSettingToggle from './AdminABACSettingToggle';
+import EditableSettingsProvider from '../settings/EditableSettingsProvider';
+
+const settingStructure = {
+ packageValue: false,
+ blocked: false,
+ public: true,
+ type: 'boolean',
+ i18nLabel: 'ABAC_Enabled',
+ i18nDescription: 'ABAC_Enabled_Description',
+} as Partial;
+
+const baseAppRoot = mockAppRoot()
+ .wrap((children) => {children})
+ .withTranslations('en', 'core', {
+ ABAC_Enabled: 'Enable ABAC',
+ ABAC_Enabled_Description: 'Enable Attribute-Based Access Control',
+ ABAC_Warning_Modal_Title: 'Disable ABAC',
+ ABAC_Warning_Modal_Confirm_Text: 'Disable',
+ Cancel: 'Cancel',
+ });
+
+describe('AdminABACSettingToggle', () => {
+ it('should render the setting toggle when setting exists', () => {
+ const { baseElement } = render(, {
+ wrapper: baseAppRoot.withSetting('ABAC_Enabled', true, settingStructure).build(),
+ });
+ expect(baseElement).toMatchSnapshot();
+ });
+
+ it('should show warning modal when disabling ABAC', async () => {
+ const user = userEvent.setup();
+ render(, {
+ wrapper: baseAppRoot.withSetting('ABAC_Enabled', true, settingStructure).build(),
+ });
+
+ const toggle = screen.getByRole('checkbox');
+ await waitFor(() => {
+ expect(toggle).not.toBeDisabled();
+ });
+ await user.click(toggle);
+
+ await waitFor(() => {
+ expect(screen.getByText('Disable ABAC')).toBeInTheDocument();
+ });
+
+ // TODO: discover how to automatically unmount all modals after each test
+ const cancelButton = screen.getByRole('button', { name: /cancel/i });
+ await user.click(cancelButton);
+ });
+
+ it('should not show warning modal when enabling ABAC', async () => {
+ const user = userEvent.setup();
+ render(, {
+ wrapper: baseAppRoot.withSetting('ABAC_Enabled', false, settingStructure).build(),
+ });
+
+ const toggle = screen.getByRole('checkbox');
+ await user.click(toggle);
+
+ // The modal should not appear when enabling ABAC
+ expect(screen.queryByText('Disable ABAC')).not.toBeInTheDocument();
+ });
+
+ it('should show warning modal when resetting setting', async () => {
+ const user = userEvent.setup();
+ render(, {
+ wrapper: baseAppRoot.withSetting('ABAC_Enabled', true, settingStructure).build(),
+ });
+
+ const resetButton = screen.getByRole('button', { name: /reset/i });
+ await user.click(resetButton);
+
+ await waitFor(() => {
+ expect(screen.getByText('Disable ABAC')).toBeInTheDocument();
+ });
+
+ // TODO: discover how to automatically unmount all modals after each test
+ const cancelButton = screen.getByRole('button', { name: /cancel/i });
+ await user.click(cancelButton);
+ });
+
+ it('should have no accessibility violations', async () => {
+ const { container } = render(, {
+ wrapper: baseAppRoot.withSetting('ABAC_Enabled', true, settingStructure).build(),
+ });
+ const results = await axe(container);
+ expect(results).toHaveNoViolations();
+ });
+
+ it('should handle setting change correctly', async () => {
+ const user = userEvent.setup();
+ render(, {
+ wrapper: baseAppRoot.withSetting('ABAC_Enabled', false, settingStructure).build(),
+ });
+
+ const toggle = await screen.findByRole('checkbox', { busy: false });
+ expect(toggle).not.toBeChecked();
+
+ await user.click(toggle);
+ expect(toggle).toBeChecked();
+ });
+
+ it('should be disabled when abac license is not installed', () => {
+ const { baseElement } = render(, {
+ wrapper: baseAppRoot.withSetting('ABAC_Enabled', true, settingStructure).build(),
+ });
+
+ const toggle = screen.getByRole('checkbox');
+ expect(toggle).toBeDisabled();
+ expect(baseElement).toMatchSnapshot();
+ });
+
+ it('should show skeleton when loading', () => {
+ const { baseElement } = render(, {
+ wrapper: baseAppRoot.withSetting('ABAC_Enabled', true, settingStructure).build(),
+ });
+ expect(baseElement).toMatchSnapshot();
+ });
+
+ it('should show reset button when value differs from package value', () => {
+ render(, {
+ wrapper: baseAppRoot.withSetting('ABAC_Enabled', true, settingStructure).build(),
+ });
+
+ expect(screen.getByRole('button', { name: /reset/i })).toBeInTheDocument();
+ });
+
+ it('should not show reset button when value matches package value', () => {
+ render(, {
+ wrapper: baseAppRoot.withSetting('ABAC_Enabled', false, settingStructure).build(),
+ });
+
+ expect(screen.queryByRole('button', { name: /reset/i })).not.toBeInTheDocument();
+ });
+});
diff --git a/apps/meteor/client/views/admin/ABAC/AdminABACSettingToggle.stories.tsx b/apps/meteor/client/views/admin/ABAC/AdminABACSettingToggle.stories.tsx
new file mode 100644
index 0000000000000..6c5626baa0dc1
--- /dev/null
+++ b/apps/meteor/client/views/admin/ABAC/AdminABACSettingToggle.stories.tsx
@@ -0,0 +1,65 @@
+import { mockAppRoot } from '@rocket.chat/mock-providers';
+import type { Meta, StoryObj } from '@storybook/react';
+
+import AdminABACSettingToggle from './AdminABACSettingToggle';
+import EditableSettingsProvider from '../settings/EditableSettingsProvider';
+
+const meta: Meta = {
+ title: 'Admin/ABAC/AdminABACSettingToggle',
+ component: AdminABACSettingToggle,
+ parameters: {
+ layout: 'padded',
+ },
+ decorators: [
+ (Story) => {
+ const AppRoot = mockAppRoot()
+ .wrap((children) => {children})
+ .withTranslations('en', 'core', {
+ ABAC_Enabled: 'Enable ABAC',
+ ABAC_Enabled_Description: 'Enable Attribute-Based Access Control',
+ ABAC_Warning_Modal_Title: 'Disable ABAC',
+ ABAC_Warning_Modal_Confirm_Text: 'Disable',
+ Cancel: 'Cancel',
+ })
+ .withSetting('ABAC_Enabled', true, {
+ packageValue: false,
+ blocked: false,
+ public: true,
+ type: 'boolean',
+ i18nLabel: 'ABAC_Enabled',
+ i18nDescription: 'ABAC_Enabled_Description',
+ })
+ .build();
+
+ return (
+
+
+
+ );
+ },
+ ],
+ args: {
+ hasABAC: true,
+ },
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {
+ hasABAC: true,
+ },
+};
+
+export const Loading: Story = {
+ args: {
+ hasABAC: 'loading',
+ },
+};
+
+export const False: Story = {
+ args: {
+ hasABAC: false,
+ },
+};
diff --git a/apps/meteor/client/views/admin/ABAC/AdminABACSettingToggle.tsx b/apps/meteor/client/views/admin/ABAC/AdminABACSettingToggle.tsx
new file mode 100644
index 0000000000000..7d7077e08364c
--- /dev/null
+++ b/apps/meteor/client/views/admin/ABAC/AdminABACSettingToggle.tsx
@@ -0,0 +1,95 @@
+import type { SettingValue } from '@rocket.chat/core-typings';
+import { useSetModal, useSettingsDispatch } from '@rocket.chat/ui-contexts';
+import { useCallback, useEffect, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import type { EditableSetting } from '../EditableSettingsContext';
+import { useEditableSetting } from '../EditableSettingsContext';
+import AdminABACWarningModal from './AdminABACWarningModal';
+import MemoizedSetting from '../settings/Setting/MemoizedSetting';
+import SettingSkeleton from '../settings/Setting/SettingSkeleton';
+
+type AdminABACSettingToggleProps = {
+ hasABAC: 'loading' | boolean;
+};
+
+const AdminABACSettingToggle = ({ hasABAC }: AdminABACSettingToggleProps) => {
+ const setting = useEditableSetting('ABAC_Enabled');
+ const setModal = useSetModal();
+ const dispatch = useSettingsDispatch();
+ const { t } = useTranslation();
+
+ const [value, setValue] = useState(setting?.value === true);
+
+ useEffect(() => {
+ setValue(setting?.value === true);
+ }, [setting]);
+
+ const onChange = useCallback(
+ (value: boolean) => {
+ if (!setting) {
+ return;
+ }
+
+ const handleChange = (value: boolean, setting: EditableSetting) => {
+ setValue(value);
+ dispatch([{ _id: setting._id, value }]);
+ };
+
+ if (value === false) {
+ return setModal(
+ {
+ handleChange(value, setting);
+ setModal();
+ }}
+ onCancel={() => setModal()}
+ />,
+ );
+ }
+ handleChange(value, setting);
+ },
+ [dispatch, setModal, setting],
+ );
+
+ const onReset = useCallback(() => {
+ if (!setting) {
+ return;
+ }
+ const value = setting.packageValue as boolean;
+ setModal(
+ {
+ setValue(value);
+ dispatch([{ _id: setting._id, value }]);
+ setModal();
+ }}
+ onCancel={() => setModal()}
+ />,
+ );
+ }, [dispatch, setModal, setting]);
+
+ if (!setting) {
+ return null;
+ }
+
+ if (hasABAC === 'loading') {
+ return ;
+ }
+
+ return (
+ onChange(value === true)}
+ onResetButtonClick={() => onReset()}
+ />
+ );
+};
+export default AdminABACSettingToggle;
diff --git a/apps/meteor/client/views/admin/ABAC/AdminABACSettings.tsx b/apps/meteor/client/views/admin/ABAC/AdminABACSettings.tsx
new file mode 100644
index 0000000000000..3741720317692
--- /dev/null
+++ b/apps/meteor/client/views/admin/ABAC/AdminABACSettings.tsx
@@ -0,0 +1,30 @@
+import { Box, Callout, Margins } from '@rocket.chat/fuselage';
+import { Trans } from 'react-i18next';
+
+import AdminABACSettingToggle from './AdminABACSettingToggle';
+import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule';
+import { links } from '../../../lib/links';
+
+const AdminABACSettings = () => {
+ const hasABAC = useHasLicenseModule('abac');
+ return (
+
+
+
+
+
+
+
+ User attributes are synchronized via LDAP
+
+ Learn more
+
+
+
+
+
+
+ );
+};
+
+export default AdminABACSettings;
diff --git a/apps/meteor/client/views/admin/ABAC/AdminABACTabs.tsx b/apps/meteor/client/views/admin/ABAC/AdminABACTabs.tsx
new file mode 100644
index 0000000000000..4fc73a491f44e
--- /dev/null
+++ b/apps/meteor/client/views/admin/ABAC/AdminABACTabs.tsx
@@ -0,0 +1,24 @@
+import { Tabs, TabsItem } from '@rocket.chat/fuselage';
+import { useRouteParameter, useRouter } from '@rocket.chat/ui-contexts';
+import { useTranslation } from 'react-i18next';
+
+const AdminABACTabs = () => {
+ const { t } = useTranslation();
+ const router = useRouter();
+ const tab = useRouteParameter('tab');
+ const handleTabClick = (tab: string) => {
+ router.navigate({
+ name: 'admin-ABAC',
+ params: { tab },
+ });
+ };
+ return (
+
+ handleTabClick('settings')}>
+ {t('Settings')}
+
+
+ );
+};
+
+export default AdminABACTabs;
diff --git a/apps/meteor/client/views/admin/ABAC/AdminABACWarningModal.tsx b/apps/meteor/client/views/admin/ABAC/AdminABACWarningModal.tsx
new file mode 100644
index 0000000000000..a6be0c83dcbcc
--- /dev/null
+++ b/apps/meteor/client/views/admin/ABAC/AdminABACWarningModal.tsx
@@ -0,0 +1,48 @@
+import { Box } from '@rocket.chat/fuselage';
+import { GenericModal } from '@rocket.chat/ui-client';
+import { useRouter } from '@rocket.chat/ui-contexts';
+import { Trans, useTranslation } from 'react-i18next';
+
+type AdminABACWarningModalProps = {
+ onConfirm: () => void;
+ onCancel: () => void;
+};
+
+const AdminABACWarningModal = ({ onConfirm, onCancel }: AdminABACWarningModalProps) => {
+ const { t } = useTranslation();
+ const router = useRouter();
+ const handleNavigate = () => {
+ onCancel();
+ router.navigate({
+ name: 'admin-ABAC',
+ params: {
+ tab: 'rooms',
+ },
+ });
+ };
+
+ return (
+
+
+ You will not be able to automatically or manually manage users in existing ABAC-managed rooms. To restore a room's default access
+ control, it must be removed from ABAC management in
+
+ {' '}
+ ABAC {'>'} Rooms
+
+ .
+
+
+ );
+};
+
+export default AdminABACWarningModal;
diff --git a/apps/meteor/client/views/admin/ABAC/__snapshots__/AdminABACSettingToggle.spec.tsx.snap b/apps/meteor/client/views/admin/ABAC/__snapshots__/AdminABACSettingToggle.spec.tsx.snap
new file mode 100644
index 0000000000000..39af2d46aa2f0
--- /dev/null
+++ b/apps/meteor/client/views/admin/ABAC/__snapshots__/AdminABACSettingToggle.spec.tsx.snap
@@ -0,0 +1,165 @@
+// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
+
+exports[`AdminABACSettingToggle should be disabled when abac license is not installed 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Enable Attribute-Based Access Control
+
+
+
+
+
+
+`;
+
+exports[`AdminABACSettingToggle should render the setting toggle when setting exists 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Enable Attribute-Based Access Control
+
+
+
+
+
+
+`;
+
+exports[`AdminABACSettingToggle should show skeleton when loading 1`] = `
+
+
+
+`;
diff --git a/apps/meteor/client/views/admin/routes.tsx b/apps/meteor/client/views/admin/routes.tsx
index 233da80cd1088..55b06e6fa8f46 100644
--- a/apps/meteor/client/views/admin/routes.tsx
+++ b/apps/meteor/client/views/admin/routes.tsx
@@ -104,6 +104,10 @@ declare module '@rocket.chat/ui-contexts' {
pathname: '/admin/feature-preview';
pattern: '/admin/feature-preview';
};
+ 'admin-ABAC': {
+ pathname: '/admin/ABAC';
+ pattern: '/admin/ABAC/:tab?/:context?/:id?';
+ };
}
}
@@ -237,3 +241,8 @@ registerAdminRoute('/feature-preview', {
name: 'admin-feature-preview',
component: lazy(() => import('./featurePreview/AdminFeaturePreviewRoute')),
});
+
+registerAdminRoute('/ABAC/:tab?/:context?/:id?', {
+ name: 'admin-ABAC',
+ component: lazy(() => import('./ABAC/AdminABACRoute')),
+});
diff --git a/apps/meteor/client/views/admin/sidebarItems.ts b/apps/meteor/client/views/admin/sidebarItems.ts
index 2c70d9e173cd8..7b907afec75e4 100644
--- a/apps/meteor/client/views/admin/sidebarItems.ts
+++ b/apps/meteor/client/views/admin/sidebarItems.ts
@@ -64,6 +64,13 @@ export const {
icon: 'user-lock',
permissionGranted: (): boolean => hasAtLeastOnePermission(['access-permissions', 'access-setting-permissions']),
},
+ {
+ href: '/admin/ABAC',
+ i18nLabel: 'ABAC',
+ icon: 'team-lock',
+ // TODO: Check what permission is needed to view the ABAC page
+ permissionGranted: (): boolean => !hasPermission('abac-management'),
+ },
{
href: '/admin/device-management',
i18nLabel: 'Device_Management',
diff --git a/apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersWithData.tsx b/apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersWithData.tsx
index 1abda763611f8..c373215c328d3 100644
--- a/apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersWithData.tsx
+++ b/apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersWithData.tsx
@@ -117,7 +117,6 @@ const RoomMembersWithData = ({ rid }: { rid: IRoom['_id'] }): ReactElement => {
reload={refetch}
onClickInvite={canCreateInviteLinks && canAddUsers ? openInvite : undefined}
onClickAdd={canAddUsers ? openAddUser : undefined}
- // @ts-expect-error to be implemented in ABAC Feature branch
isABACRoom={Boolean(room?.abacAttributes)}
/>
);
diff --git a/apps/meteor/ee/server/settings/abac.ts b/apps/meteor/ee/server/settings/abac.ts
index e61c61f730c9b..f187e17703cdd 100644
--- a/apps/meteor/ee/server/settings/abac.ts
+++ b/apps/meteor/ee/server/settings/abac.ts
@@ -13,6 +13,7 @@ export function addSettings(): void {
public: true,
invalidValue: false,
section: 'ABAC',
+ i18nDescription: 'ABAC_Enabled_Description',
});
},
);
diff --git a/apps/meteor/tests/mocks/data.ts b/apps/meteor/tests/mocks/data.ts
index 1dde2432ca3be..ecdca6b206a23 100644
--- a/apps/meteor/tests/mocks/data.ts
+++ b/apps/meteor/tests/mocks/data.ts
@@ -233,6 +233,7 @@ export const createFakeLicenseInfo = (partial: Partial",
- "ABAC": "Attribute Based Access Control (ABAC)",
+ "ABAC": "Attribute Based Access Control",
"ABAC_Enabled": "Enable Attribute Based Access Control (ABAC)",
+ "ABAC_Enabled_Description": "Controls access to rooms based on user and room attributes.",
+ "ABAC_Enabled_callout": "User attributes are synchronized via LDAP. <1>Learn more1>",
+ "ABAC_Learn_More": "Learn about ABAC",
+ "ABAC_automatically_disabled_callout": "ABAC automatically disabled",
+ "ABAC_automatically_disabled_callout_description": "Renew your license to continue using all <1>ABAC capabilities without restriction1>.",
+ "ABAC_Warning_Modal_Title": "Deactivate ABAC",
+ "ABAC_Warning_Modal_Confirm_Text": "Deactivate ABAC",
+ "ABAC_Warning_Modal_Content": "You will not be able to automatically or manually manage users in existing ABAC-managed rooms. To restore a room's default access control, it must be removed from ABAC management in <1>ABAC > Rooms1>.",
"abac-management": "Manage ABAC configuration",
"abac_removed_user_from_the_room": "was removed by ABAC",
"AI_Actions": "AI actions",