[MM-64367] Update property/attribute naming convetion (#31168)

Automatic Merge
Этот коммит содержится в:
Ibrahim Serdar Acikgoz
2025-06-02 09:00:09 +02:00
коммит произвёл GitHub
родитель c90dfa4895
Коммит a457d3b73c
19 изменённых файлов: 172 добавлений и 112 удалений

Просмотреть файл

@@ -197,7 +197,7 @@ export default function PolicyList(props: Props): JSX.Element {
<Menu.Item <Menu.Item
id={`policy-menu-edit-${policy.id}`} id={`policy-menu-edit-${policy.id}`}
onClick={() => { onClick={() => {
history.push(`/admin_console/user_management/attribute_based_access_control/edit_policy/${policy.id}`); history.push(`/admin_console/system_attributes/attribute_based_access_control/edit_policy/${policy.id}`);
}} }}
leadingElement={<i className='icon icon-pencil-outline'/>} leadingElement={<i className='icon icon-pencil-outline'/>}
labels={ labels={
@@ -229,7 +229,7 @@ export default function PolicyList(props: Props): JSX.Element {
if (props.onPolicySelected) { if (props.onPolicySelected) {
props.onPolicySelected(policy); props.onPolicySelected(policy);
} else { } else {
history.push(`/admin_console/user_management/attribute_based_access_control/edit_policy/${policy.id}`); history.push(`/admin_console/system_attributes/attribute_based_access_control/edit_policy/${policy.id}`);
} }
}, },
}; };
@@ -326,7 +326,7 @@ export default function PolicyList(props: Props): JSX.Element {
<button <button
className='btn btn-primary' className='btn btn-primary'
onClick={() => { onClick={() => {
history.push('/admin_console/user_management/attribute_based_access_control/edit_policy'); history.push('/admin_console/system_attributes/attribute_based_access_control/edit_policy');
}} }}
> >
<i className='icon icon-plus'/> <i className='icon icon-plus'/>

Просмотреть файл

@@ -10,7 +10,7 @@ exports[`components/admin_console/access_control/policy_details/PolicyDetails sh
<div> <div>
<Connect(Component) <Connect(Component)
className="fa fa-angle-left back" className="fa fa-angle-left back"
to="/admin_console/user_management/attribute_based_access_control" to="/admin_console/system_attributes/attribute_based_access_control"
/> />
<MemoizedFormattedMessage <MemoizedFormattedMessage
defaultMessage="Edit Access Control Policy" defaultMessage="Edit Access Control Policy"
@@ -193,7 +193,7 @@ exports[`components/admin_console/access_control/policy_details/PolicyDetails sh
/> />
<Connect(Component) <Connect(Component)
className="btn btn-quaternary" className="btn btn-quaternary"
to="/admin_console/user_management/attribute_based_access_control" to="/admin_console/system_attributes/attribute_based_access_control"
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
defaultMessage="Cancel" defaultMessage="Cancel"
@@ -214,7 +214,7 @@ exports[`components/admin_console/access_control/policy_details/PolicyDetails sh
<div> <div>
<Connect(Component) <Connect(Component)
className="fa fa-angle-left back" className="fa fa-angle-left back"
to="/admin_console/user_management/attribute_based_access_control" to="/admin_console/system_attributes/attribute_based_access_control"
/> />
<MemoizedFormattedMessage <MemoizedFormattedMessage
defaultMessage="Edit Access Control Policy" defaultMessage="Edit Access Control Policy"
@@ -368,7 +368,7 @@ exports[`components/admin_console/access_control/policy_details/PolicyDetails sh
/> />
<Connect(Component) <Connect(Component)
className="btn btn-quaternary" className="btn btn-quaternary"
to="/admin_console/user_management/attribute_based_access_control" to="/admin_console/system_attributes/attribute_based_access_control"
> >
<MemoizedFormattedMessage <MemoizedFormattedMessage
defaultMessage="Cancel" defaultMessage="Cancel"

Просмотреть файл

@@ -239,7 +239,7 @@ function PolicyDetails({
setSaveNeeded(false); setSaveNeeded(false);
setShowConfirmationModal(false); setShowConfirmationModal(false);
actions.setNavigationBlocked(false); actions.setNavigationBlocked(false);
getHistory().push('/admin_console/user_management/attribute_based_access_control'); getHistory().push('/admin_console/system_attributes/attribute_based_access_control');
}; };
const handleDelete = async () => { const handleDelete = async () => {
@@ -275,7 +275,7 @@ function PolicyDetails({
} }
if (success) { if (success) {
getHistory().push('/admin_console/user_management/attribute_based_access_control'); getHistory().push('/admin_console/system_attributes/attribute_based_access_control');
} }
}; };
@@ -331,7 +331,7 @@ function PolicyDetails({
<AdminHeader withBackButton={true}> <AdminHeader withBackButton={true}>
<div> <div>
<BlockableLink <BlockableLink
to='/admin_console/user_management/attribute_based_access_control' to='/admin_console/system_attributes/attribute_based_access_control'
className='fa fa-angle-left back' className='fa fa-angle-left back'
/> />
<FormattedMessage <FormattedMessage
@@ -399,7 +399,7 @@ function PolicyDetails({
} }
text={formatMessage({ text={formatMessage({
id: 'admin.access_control.policy.edit_policy.notice.text', id: 'admin.access_control.policy.edit_policy.notice.text',
defaultMessage: 'You havent configured any user attributes yet. Attribute-Based Access Control requires user attributes that are either synced from an external system (like LDAP or SAML) or manually configured and enabled on this server. To start using attribute based access, please configure user attributes in System Properties.', defaultMessage: 'You havent configured any user attributes yet. Attribute-Based Access Control requires user attributes that are either synced from an external system (like LDAP or SAML) or manually configured and enabled on this server. To start using attribute based access, please configure user attributes in System Attributes.',
})} })}
primaryButton={{ primaryButton={{
text: formatMessage({ text: formatMessage({
@@ -407,7 +407,7 @@ function PolicyDetails({
defaultMessage: 'Configure user attributes', defaultMessage: 'Configure user attributes',
}), }),
onClick: () => { onClick: () => {
getHistory().push('/admin_console/site_config/system_properties'); getHistory().push('/admin_console/system_attributes/user_attributes');
}, },
}} }}
/> />
@@ -642,7 +642,7 @@ function PolicyDetails({
/> />
<BlockableLink <BlockableLink
className='btn btn-quaternary' className='btn btn-quaternary'
to='/admin_console/user_management/attribute_based_access_control' to='/admin_console/system_attributes/attribute_based_access_control'
> >
<FormattedMessage <FormattedMessage
id='admin.access_control.edit_policy.cancel' id='admin.access_control.edit_policy.cancel'

Просмотреть файл

@@ -8,7 +8,7 @@ import type {MessageDescriptor} from 'react-intl';
import {FormattedMessage, defineMessage, defineMessages} from 'react-intl'; import {FormattedMessage, defineMessage, defineMessages} from 'react-intl';
import {Link} from 'react-router-dom'; import {Link} from 'react-router-dom';
import {AccountMultipleOutlineIcon, ChartBarIcon, CogOutlineIcon, CreditCardOutlineIcon, FlaskOutlineIcon, FormatListBulletedIcon, InformationOutlineIcon, PowerPlugOutlineIcon, ServerVariantIcon, ShieldOutlineIcon, SitemapIcon} from '@mattermost/compass-icons/components'; import {AccountMultipleOutlineIcon, ChartBarIcon, CogOutlineIcon, CreditCardOutlineIcon, FlaskOutlineIcon, FormatListBulletedIcon, InformationOutlineIcon, PowerPlugOutlineIcon, ServerVariantIcon, ShieldOutlineIcon, SitemapIcon, TableLargeIcon} from '@mattermost/compass-icons/components';
import type {CloudState, Product} from '@mattermost/types/cloud'; import type {CloudState, Product} from '@mattermost/types/cloud';
import type {AdminConfig, ClientLicense} from '@mattermost/types/config'; import type {AdminConfig, ClientLicense} from '@mattermost/types/config';
import type {Job} from '@mattermost/types/jobs'; import type {Job} from '@mattermost/types/jobs';
@@ -668,8 +668,36 @@ const AdminDefinition: AdminDefinitionType = {
}, },
restrictedIndicator: getRestrictedIndicator(true, LicenseSkus.Enterprise), restrictedIndicator: getRestrictedIndicator(true, LicenseSkus.Enterprise),
}, },
},
},
system_attributes: {
icon: (
<TableLargeIcon
size={16}
color={'currentColor'}
/>
),
sectionTitle: defineMessage({id: 'admin.sidebar.systemAttributes', defaultMessage: 'System Attributes'}),
isHidden: it.not(it.all(
it.minLicenseTier(LicenseSkus.Enterprise),
it.configIsTrue('FeatureFlags', 'CustomProfileAttributes'),
)),
subsections: {
system_properties: {
url: 'system_attributes/user_attributes',
title: defineMessage({id: 'admin.sidebar.user_attributes', defaultMessage: 'User Attributes'}),
searchableStrings: systemPropertiesSearchableStrings,
isHidden: it.not(it.all(
it.minLicenseTier(LicenseSkus.Enterprise),
it.configIsTrue('FeatureFlags', 'CustomProfileAttributes'),
)),
schema: {
id: 'SystemProperties',
component: SystemProperties,
},
},
access_control_policy_details_edit: { access_control_policy_details_edit: {
url: `user_management/attribute_based_access_control/edit_policy/:policy_id(${ID_PATH_PATTERN})`, url: `system_attributes/attribute_based_access_control/edit_policy/:policy_id(${ID_PATH_PATTERN})`,
isHidden: it.any( isHidden: it.any(
it.configIsFalse('AccessControlSettings', 'EnableAttributeBasedAccessControl'), it.configIsFalse('AccessControlSettings', 'EnableAttributeBasedAccessControl'),
it.not(it.licensedForSku(LicenseSkus.EnterpriseAdvanced)), it.not(it.licensedForSku(LicenseSkus.EnterpriseAdvanced)),
@@ -683,10 +711,9 @@ const AdminDefinition: AdminDefinitionType = {
id: 'AccessControlPolicy', id: 'AccessControlPolicy',
component: PolicyDetails, component: PolicyDetails,
}, },
}, },
access_control_policy_details: { access_control_policy_details: {
url: 'user_management/attribute_based_access_control/edit_policy', url: 'system_attributes/attribute_based_access_control/edit_policy',
isHidden: it.any( isHidden: it.any(
it.configIsFalse('AccessControlSettings', 'EnableAttributeBasedAccessControl'), it.configIsFalse('AccessControlSettings', 'EnableAttributeBasedAccessControl'),
it.not(it.licensedForSku(LicenseSkus.EnterpriseAdvanced)), it.not(it.licensedForSku(LicenseSkus.EnterpriseAdvanced)),
@@ -700,7 +727,7 @@ const AdminDefinition: AdminDefinitionType = {
}, },
}, },
attribute_based_access_control: { attribute_based_access_control: {
url: 'user_management/attribute_based_access_control', url: 'system_attributes/attribute_based_access_control',
title: defineMessage({id: 'admin.sidebar.attributeBasedAccessControl', defaultMessage: 'Attribute-Based Access'}), title: defineMessage({id: 'admin.sidebar.attributeBasedAccessControl', defaultMessage: 'Attribute-Based Access'}),
isHidden: it.any( isHidden: it.any(
it.not(it.licensedForSku(LicenseSkus.EnterpriseAdvanced)), it.not(it.licensedForSku(LicenseSkus.EnterpriseAdvanced)),
@@ -720,10 +747,10 @@ const AdminDefinition: AdminDefinitionType = {
type: 'bool', type: 'bool',
key: 'AccessControlSettings.EnableAttributeBasedAccessControl', key: 'AccessControlSettings.EnableAttributeBasedAccessControl',
label: defineMessage({id: 'admin.accesscontrol.enableTitle', defaultMessage: 'Allow attribute based access controls on this server'}), label: defineMessage({id: 'admin.accesscontrol.enableTitle', defaultMessage: 'Allow attribute based access controls on this server'}),
help_text: defineMessage({id: 'admin.accesscontrol.enableDesc', defaultMessage: 'Allow access restrictions based on user attributes using custom access policies. To effectively use this feature, you must define user attributes (properties) in the {userAttributes} section.'}), help_text: defineMessage({id: 'admin.accesscontrol.enableDesc', defaultMessage: 'Allow access restrictions based on user attributes using custom access policies. To effectively use this feature, you must define user attributes in the {userAttributes} section.'}),
help_text_values: { help_text_values: {
userAttributes: ( userAttributes: (
<a href='../site_config/system_properties'> <a href='../system_attributes/user_attributes'>
<FormattedMessage <FormattedMessage
id='admin.system_properties.user_properties.title' id='admin.system_properties.user_properties.title'
defaultMessage='User Attributes' defaultMessage='User Attributes'
@@ -767,7 +794,7 @@ const AdminDefinition: AdminDefinitionType = {
restrictedIndicator: getRestrictedIndicator(false, LicenseSkus.EnterpriseAdvanced), restrictedIndicator: getRestrictedIndicator(false, LicenseSkus.EnterpriseAdvanced),
}, },
attribute_based_access_control_feature_discovery: { attribute_based_access_control_feature_discovery: {
url: 'user_management/attribute_based_access_control', url: 'system_attributes/attribute_based_access_control',
isDiscovery: true, isDiscovery: true,
title: defineMessage({id: 'admin.sidebar.attributeBasedAccessControl', defaultMessage: 'Attribute-Based Access'}), title: defineMessage({id: 'admin.sidebar.attributeBasedAccessControl', defaultMessage: 'Attribute-Based Access'}),
isHidden: it.any( isHidden: it.any(
@@ -2458,19 +2485,6 @@ const AdminDefinition: AdminDefinitionType = {
], ],
}, },
}, },
system_properties: {
url: 'site_config/system_properties',
title: defineMessage({id: 'admin.sidebar.system_properties', defaultMessage: 'System Properties'}),
searchableStrings: systemPropertiesSearchableStrings,
isHidden: it.not(it.all(
it.minLicenseTier(LicenseSkus.Enterprise),
it.configIsTrue('FeatureFlags', 'CustomProfileAttributes'),
)),
schema: {
id: 'SystemProperties',
component: SystemProperties,
},
},
localization: { localization: {
url: 'site_config/localization', url: 'site_config/localization',
title: defineMessage({id: 'admin.sidebar.localization', defaultMessage: 'Localization'}), title: defineMessage({id: 'admin.sidebar.localization', defaultMessage: 'Localization'}),

Просмотреть файл

@@ -1496,10 +1496,40 @@ exports[`components/AdminSidebar should match snapshot with license with enterpr
/> />
} }
/> />
</AdminSidebarCategory>
<AdminSidebarCategory
definitionKey="system_attributes"
icon={
<TableLargeIcon
color="currentColor"
size={16}
/>
}
key="system_attributes"
parentLink="/admin_console"
sectionClass=""
title={
<Memo(MemoizedFormattedMessage)
defaultMessage="System Attributes"
id="admin.sidebar.systemAttributes"
/>
}
>
<AdminSidebarSection <AdminSidebarSection
definitionKey="user_management.attribute_based_access_control_feature_discovery" definitionKey="system_attributes.system_properties"
key="user_management.attribute_based_access_control_feature_discovery" key="system_attributes.system_properties"
name="user_management/attribute_based_access_control" name="system_attributes/user_attributes"
title={
<Memo(MemoizedFormattedMessage)
defaultMessage="User Attributes"
id="admin.sidebar.user_attributes"
/>
}
/>
<AdminSidebarSection
definitionKey="system_attributes.attribute_based_access_control_feature_discovery"
key="system_attributes.attribute_based_access_control_feature_discovery"
name="system_attributes/attribute_based_access_control"
restrictedIndicator={ restrictedIndicator={
<RestrictedIndicator <RestrictedIndicator
blocked={true} blocked={true}
@@ -1701,17 +1731,6 @@ exports[`components/AdminSidebar should match snapshot with license with enterpr
/> />
} }
/> />
<AdminSidebarSection
definitionKey="site.system_properties"
key="site.system_properties"
name="site_config/system_properties"
title={
<Memo(MemoizedFormattedMessage)
defaultMessage="System Properties"
id="admin.sidebar.system_properties"
/>
}
/>
<AdminSidebarSection <AdminSidebarSection
definitionKey="site.localization" definitionKey="site.localization"
key="site.localization" key="site.localization"
@@ -2567,10 +2586,40 @@ exports[`components/AdminSidebar should match snapshot with license with enterpr
/> />
} }
/> />
</AdminSidebarCategory>
<AdminSidebarCategory
definitionKey="system_attributes"
icon={
<TableLargeIcon
color="currentColor"
size={16}
/>
}
key="system_attributes"
parentLink="/admin_console"
sectionClass=""
title={
<Memo(MemoizedFormattedMessage)
defaultMessage="System Attributes"
id="admin.sidebar.systemAttributes"
/>
}
>
<AdminSidebarSection <AdminSidebarSection
definitionKey="user_management.attribute_based_access_control" definitionKey="system_attributes.system_properties"
key="user_management.attribute_based_access_control" key="system_attributes.system_properties"
name="user_management/attribute_based_access_control" name="system_attributes/user_attributes"
title={
<Memo(MemoizedFormattedMessage)
defaultMessage="User Attributes"
id="admin.sidebar.user_attributes"
/>
}
/>
<AdminSidebarSection
definitionKey="system_attributes.attribute_based_access_control"
key="system_attributes.attribute_based_access_control"
name="system_attributes/attribute_based_access_control"
title={ title={
<Memo(MemoizedFormattedMessage) <Memo(MemoizedFormattedMessage)
defaultMessage="Attribute-Based Access" defaultMessage="Attribute-Based Access"
@@ -2759,17 +2808,6 @@ exports[`components/AdminSidebar should match snapshot with license with enterpr
/> />
} }
/> />
<AdminSidebarSection
definitionKey="site.system_properties"
key="site.system_properties"
name="site_config/system_properties"
title={
<Memo(MemoizedFormattedMessage)
defaultMessage="System Properties"
id="admin.sidebar.system_properties"
/>
}
/>
<AdminSidebarSection <AdminSidebarSection
definitionKey="site.localization" definitionKey="site.localization"
key="site.localization" key="site.localization"

Просмотреть файл

@@ -136,7 +136,7 @@ const CustomProfileAttributes: React.FC<Props> = (props: Props): JSX.Element | n
values={{ values={{
link: (msg: string) => ( link: (msg: string) => (
<Link <Link
to='/admin_console/site_config/system_properties' to='/admin_console/system_attributes/user_attributes'
> >
{msg} {msg}
</Link> </Link>

Просмотреть файл

@@ -73,7 +73,7 @@ describe('SystemProperties', () => {
expect(screen.queryByText('Loading')).not.toBeInTheDocument(); expect(screen.queryByText('Loading')).not.toBeInTheDocument();
}); });
expect(screen.getByRole('heading', {name: 'User Properties'})).toBeInTheDocument(); expect(screen.getByRole('heading', {name: 'Configure user attributes'})).toBeInTheDocument();
expect(screen.queryByDisplayValue('test attribute 0')).toBeInTheDocument(); expect(screen.queryByDisplayValue('test attribute 0')).toBeInTheDocument();
expect(screen.queryByDisplayValue('test attribute 1')).toBeInTheDocument(); expect(screen.queryByDisplayValue('test attribute 1')).toBeInTheDocument();

Просмотреть файл

@@ -58,11 +58,11 @@ export default function SystemProperties(props: Props) {
<FormattedMessage <FormattedMessage
tagName={SectionHeading} tagName={SectionHeading}
id='admin.system_properties.user_properties.title' id='admin.system_properties.user_properties.title'
defaultMessage='User Properties' defaultMessage='Configure user attributes'
/> />
<FormattedMessage <FormattedMessage
id='admin.system_properties.user_properties.subtitle' id='admin.system_properties.user_properties.subtitle'
defaultMessage='Customize the properties to show in user profiles' defaultMessage='Attributes will be shown in user profile and can be used in access control policies.'
/> />
</hgroup> </hgroup>
</SectionHeader> </SectionHeader>
@@ -91,7 +91,7 @@ export default function SystemProperties(props: Props) {
} }
const msg = defineMessages({ const msg = defineMessages({
pageTitle: {id: 'admin.sidebar.system_properties', defaultMessage: 'System Properties'}, pageTitle: {id: 'admin.sidebar.user_attributes', defaultMessage: 'User Attributes'},
}); });
export const searchableStrings: SearchableStrings = Object.values(msg); export const searchableStrings: SearchableStrings = Object.values(msg);

Просмотреть файл

@@ -36,8 +36,8 @@ describe('RemoveUserPropertyFieldModal', () => {
/>, />,
); );
expect(screen.getByText('Delete Test Field property')).toBeInTheDocument(); expect(screen.getByText('Delete Test Field attribute')).toBeInTheDocument();
expect(screen.getByText('Deleting this property will remove all user-defined values associated with it.')).toBeInTheDocument(); expect(screen.getByText('Deleting this attribute will remove all user-defined values associated with it.')).toBeInTheDocument();
expect(screen.getByText('Delete')).toBeInTheDocument(); expect(screen.getByText('Delete')).toBeInTheDocument();
}); });

Просмотреть файл

@@ -49,7 +49,7 @@ function RemoveUserPropertyFieldModal({
const title = formatMessage({ const title = formatMessage({
id: 'admin.system_properties.confirm.delete.title', id: 'admin.system_properties.confirm.delete.title',
defaultMessage: 'Delete {name} property', defaultMessage: 'Delete {name} attribute',
}, {name}); }, {name});
const confirmButtonText = formatMessage({ const confirmButtonText = formatMessage({
@@ -60,7 +60,7 @@ function RemoveUserPropertyFieldModal({
const message = ( const message = (
<FormattedMessage <FormattedMessage
id={'admin.system_properties.confirm.delete.text'} id={'admin.system_properties.confirm.delete.text'}
defaultMessage={'Deleting this property will remove all user-defined values associated with it.'} defaultMessage={'Deleting this attribute will remove all user-defined values associated with it.'}
/> />
); );

Просмотреть файл

@@ -118,8 +118,8 @@ describe('UserPropertyDotMenu', () => {
fireEvent.click(menuButton); fireEvent.click(menuButton);
// Verify both link options are shown // Verify both link options are shown
expect(screen.getByText('Link property to AD/LDAP')).toBeInTheDocument(); expect(screen.getByText('Link attribute to AD/LDAP')).toBeInTheDocument();
expect(screen.getByText('Link property to SAML')).toBeInTheDocument(); expect(screen.getByText('Link attribute to SAML')).toBeInTheDocument();
}); });
it('hides LDAP and SAML link menu options for pending fields', async () => { it('hides LDAP and SAML link menu options for pending fields', async () => {
@@ -135,8 +135,8 @@ describe('UserPropertyDotMenu', () => {
fireEvent.click(menuButton); fireEvent.click(menuButton);
// Verify both link options are not shown // Verify both link options are not shown
expect(screen.queryByText('Link property to AD/LDAP')).not.toBeInTheDocument(); expect(screen.queryByText('Link attribute to AD/LDAP')).not.toBeInTheDocument();
expect(screen.queryByText('Link property to SAML')).not.toBeInTheDocument(); expect(screen.queryByText('Link attribute to SAML')).not.toBeInTheDocument();
}); });
it('shows "Edit link with" text when LDAP attribute is linked', async () => { it('shows "Edit link with" text when LDAP attribute is linked', async () => {
@@ -187,7 +187,7 @@ describe('UserPropertyDotMenu', () => {
fireEvent.click(menuButton); fireEvent.click(menuButton);
// Click the duplicate option // Click the duplicate option
fireEvent.click(screen.getByText(/Duplicate property/)); fireEvent.click(screen.getByText(/Duplicate attribute/));
// Wait for createField to be called // Wait for createField to be called
await waitFor(() => { await waitFor(() => {
@@ -207,7 +207,7 @@ describe('UserPropertyDotMenu', () => {
fireEvent.click(menuButton); fireEvent.click(menuButton);
// Verify duplicate option is not shown // Verify duplicate option is not shown
expect(screen.queryByText(/Duplicate property/)).not.toBeInTheDocument(); expect(screen.queryByText(/Duplicate attribute/)).not.toBeInTheDocument();
}); });
it('handles field deletion with confirmation when field exists in DB', async () => { it('handles field deletion with confirmation when field exists in DB', async () => {
@@ -218,12 +218,12 @@ describe('UserPropertyDotMenu', () => {
fireEvent.click(menuButton); fireEvent.click(menuButton);
// Click delete option // Click delete option
const deleteOption = screen.getByRole('menuitem', {name: /Delete property/}); const deleteOption = screen.getByRole('menuitem', {name: /Delete attribute/});
fireEvent.click(deleteOption); fireEvent.click(deleteOption);
await waitFor(() => { await waitFor(() => {
// Verify the delete modal is shown // Verify the delete modal is shown
expect(screen.getByText('Delete Test Field property')).toBeInTheDocument(); expect(screen.getByText('Delete Test Field attribute')).toBeInTheDocument();
}); });
// click delete confirm button // click delete confirm button
@@ -250,7 +250,7 @@ describe('UserPropertyDotMenu', () => {
fireEvent.click(menuButton); fireEvent.click(menuButton);
// Click delete option // Click delete option
const deleteOption = screen.getByRole('menuitem', {name: /Delete property/}); const deleteOption = screen.getByRole('menuitem', {name: /Delete attribute/});
fireEvent.click(deleteOption); fireEvent.click(deleteOption);
await waitFor(() => { await waitFor(() => {

Просмотреть файл

@@ -194,7 +194,7 @@ const DotMenu = ({
) : ( ) : (
<FormattedMessage <FormattedMessage
id='admin.system_properties.user_properties.dotmenu.ad_ldap.link_property.label' id='admin.system_properties.user_properties.dotmenu.ad_ldap.link_property.label'
defaultMessage={'Link property to AD/LDAP'} defaultMessage={'Link attribute to AD/LDAP'}
/> />
)} )}
/>, />,
@@ -215,7 +215,7 @@ const DotMenu = ({
) : ( ) : (
<FormattedMessage <FormattedMessage
id='admin.system_properties.user_properties.dotmenu.saml.link_property.label' id='admin.system_properties.user_properties.dotmenu.saml.link_property.label'
defaultMessage={'Link property to SAML'} defaultMessage={'Link attribute to SAML'}
/> />
)} )}
/>, />,
@@ -229,7 +229,7 @@ const DotMenu = ({
labels={( labels={(
<FormattedMessage <FormattedMessage
id='admin.system_properties.user_properties.dotmenu.duplicate.label' id='admin.system_properties.user_properties.dotmenu.duplicate.label'
defaultMessage={'Duplicate property'} defaultMessage={'Duplicate attribute'}
/> />
)} )}
/> />
@@ -242,7 +242,7 @@ const DotMenu = ({
labels={( labels={(
<FormattedMessage <FormattedMessage
id='admin.system_properties.user_properties.dotmenu.delete.label' id='admin.system_properties.user_properties.dotmenu.delete.label'
defaultMessage={'Delete property'} defaultMessage={'Delete attribute'}
/> />
)} )}
/> />

Просмотреть файл

@@ -77,11 +77,11 @@ describe('UserPropertiesTable', () => {
); );
}; };
it('renders table with correct property fields', () => { it('renders table with correct attribute fields', () => {
renderComponent(); renderComponent();
// Check column headers // Check column headers
expect(screen.getByText('Property')).toBeInTheDocument(); expect(screen.getByText('Attribute')).toBeInTheDocument();
expect(screen.getByText('Type')).toBeInTheDocument(); expect(screen.getByText('Type')).toBeInTheDocument();
expect(screen.getByText('Values')).toBeInTheDocument(); expect(screen.getByText('Values')).toBeInTheDocument();
expect(screen.getByText('Actions')).toBeInTheDocument(); expect(screen.getByText('Actions')).toBeInTheDocument();
@@ -162,7 +162,7 @@ describe('UserPropertiesTable', () => {
// Validation error should be shown // Validation error should be shown
await waitFor(() => { await waitFor(() => {
expect(screen.getByText('Please enter a property name.')).toBeInTheDocument(); expect(screen.getByText('Please enter an attribute name.')).toBeInTheDocument();
}); });
}); });
}); });

Просмотреть файл

@@ -68,7 +68,7 @@ export const useUserPropertiesTable = (): SectionHook => {
<PlusIcon size={16}/> <PlusIcon size={16}/>
<FormattedMessage <FormattedMessage
id='admin.system_properties.user_properties.add_property' id='admin.system_properties.user_properties.add_property'
defaultMessage='Add property' defaultMessage='Add attribute'
/> />
</LinkButton> </LinkButton>
)} )}
@@ -112,7 +112,7 @@ export function UserPropertiesTable({
<ColHeaderLeft> <ColHeaderLeft>
<FormattedMessage <FormattedMessage
id='admin.system_properties.user_properties.table.property' id='admin.system_properties.user_properties.table.property'
defaultMessage='Property' defaultMessage='Attribute'
/> />
</ColHeaderLeft> </ColHeaderLeft>
); );
@@ -128,7 +128,7 @@ export function UserPropertiesTable({
<FormattedMessage <FormattedMessage
tagName={DangerText} tagName={DangerText}
id='admin.system_properties.user_properties.table.validation.name_required' id='admin.system_properties.user_properties.table.validation.name_required'
defaultMessage='Please enter a property name.' defaultMessage='Please enter an attribute name.'
/> />
); );
} else if (warningId === ValidationWarningNameUnique) { } else if (warningId === ValidationWarningNameUnique) {
@@ -136,7 +136,7 @@ export function UserPropertiesTable({
<FormattedMessage <FormattedMessage
tagName={DangerText} tagName={DangerText}
id='admin.system_properties.user_properties.table.validation.name_unique' id='admin.system_properties.user_properties.table.validation.name_unique'
defaultMessage='Property names must be unique.' defaultMessage='Attribute names must be unique.'
/> />
); );
} else if (warningId === ValidationWarningNameTaken) { } else if (warningId === ValidationWarningNameTaken) {
@@ -144,7 +144,7 @@ export function UserPropertiesTable({
<FormattedMessage <FormattedMessage
tagName={DangerText} tagName={DangerText}
id='admin.system_properties.user_properties.table.validation.name_taken' id='admin.system_properties.user_properties.table.validation.name_taken'
defaultMessage='Property name already taken.' defaultMessage='Attribute name already taken.'
/> />
); );
} }
@@ -154,7 +154,7 @@ export function UserPropertiesTable({
<EditCell <EditCell
strong={true} strong={true}
value={getValue()} value={getValue()}
label={formatMessage({id: 'admin.system_properties.user_properties.table.property_name.input.name', defaultMessage: 'Property Name'})} label={formatMessage({id: 'admin.system_properties.user_properties.table.property_name.input.name', defaultMessage: 'Attribute Name'})}
deleted={toDelete} deleted={toDelete}
borderless={!warning} borderless={!warning}
testid='property-field-input' testid='property-field-input'

Просмотреть файл

@@ -103,7 +103,7 @@ describe('UserPropertyTypeMenu', () => {
fireEvent.click(screen.getByText('Text')); fireEvent.click(screen.getByText('Text'));
// Type in the filter input // Type in the filter input
const filterInput = screen.getByRole('textbox', {name: 'Property type'}); const filterInput = screen.getByRole('textbox', {name: 'Attribute type'});
fireEvent.change(filterInput, {target: {value: 'multi'}}); fireEvent.change(filterInput, {target: {value: 'multi'}});
// Should only see Multi-select now // Should only see Multi-select now

Просмотреть файл

@@ -74,7 +74,7 @@ const SelectType = (props: Props) => {
key='filter_types' key='filter_types'
id='filter_types' id='filter_types'
type='text' type='text'
placeholder={formatMessage({id: 'admin.system_properties.user_properties.table.filter_type', defaultMessage: 'Property type'})} placeholder={formatMessage({id: 'admin.system_properties.user_properties.table.filter_type', defaultMessage: 'Attribute type'})}
className='search-teams-selector-search' className='search-teams-selector-search'
value={filter} value={filter}
onChange={onFilterChange} onChange={onFilterChange}

Просмотреть файл

@@ -301,7 +301,7 @@
"admin.access_control.policy.edit_policy.error.unassign_channels": "Error unassigning channels: {error}", "admin.access_control.policy.edit_policy.error.unassign_channels": "Error unassigning channels: {error}",
"admin.access_control.policy.edit_policy.error.update_active_status": "Error updating policy active status: {error}", "admin.access_control.policy.edit_policy.error.update_active_status": "Error updating policy active status: {error}",
"admin.access_control.policy.edit_policy.notice.button": "Configure user attributes", "admin.access_control.policy.edit_policy.notice.button": "Configure user attributes",
"admin.access_control.policy.edit_policy.notice.text": "You havent configured any user attributes yet. Attribute-Based Access Control requires user attributes that are either synced from an external system (like LDAP or SAML) or manually configured and enabled on this server. To start using attribute based access, please configure user attributes in System Properties.", "admin.access_control.policy.edit_policy.notice.text": "You havent configured any user attributes yet. Attribute-Based Access Control requires user attributes that are either synced from an external system (like LDAP or SAML) or manually configured and enabled on this server. To start using attribute based access, please configure user attributes in System Attributes.",
"admin.access_control.policy.edit_policy.notice.title": "Please add user attributes and values to use Attribute-Based Access Control", "admin.access_control.policy.edit_policy.notice.title": "Please add user attributes and values to use Attribute-Based Access Control",
"admin.access_control.policy.edit_policy.policyName": "Access control policy name:", "admin.access_control.policy.edit_policy.policyName": "Access control policy name:",
"admin.access_control.policy.edit_policy.policyName.placeholder": "Add a unique policy name", "admin.access_control.policy.edit_policy.policyName.placeholder": "Add a unique policy name",
@@ -814,7 +814,7 @@
"admin.customization.uniqueEmojiReactionLimitPerPostDesc": "The number of unique emoji reactions that can be added to a post. Increasing this limit could lead to poor client performance. Maximum is 500.", "admin.customization.uniqueEmojiReactionLimitPerPostDesc": "The number of unique emoji reactions that can be added to a post. Increasing this limit could lead to poor client performance. Maximum is 500.",
"admin.customization.uniqueEmojiReactionLimitPerPostPlaceholder": "E.g.: 25", "admin.customization.uniqueEmojiReactionLimitPerPostPlaceholder": "E.g.: 25",
"admin.customProfileAttribDesc": "(Optional) The attribute in the SAML Assertion that will be used to populate the {name} of users in Mattermost.", "admin.customProfileAttribDesc": "(Optional) The attribute in the SAML Assertion that will be used to populate the {name} of users in Mattermost.",
"admin.customProfileAttributes.subtitle": "You can add or remove custom profile attributes by going to the <link>system properties page</link>.", "admin.customProfileAttributes.subtitle": "You can add or remove custom profile attributes by going to the <link>user attributes page</link>.",
"admin.customProfileAttributes.title": "Custom profile attributes sync", "admin.customProfileAttributes.title": "Custom profile attributes sync",
"admin.customProfileAttribWarning": "(Warning) This attribute will be converted to a TEXT attribute, if the field is set to synchronize.", "admin.customProfileAttribWarning": "(Warning) This attribute will be converted to a TEXT attribute, if the field is set to synchronize.",
"admin.data_grid.empty": "No items found", "admin.data_grid.empty": "No items found",
@@ -2661,10 +2661,11 @@
"admin.sidebar.siteStatistics": "Site Statistics", "admin.sidebar.siteStatistics": "Site Statistics",
"admin.sidebar.smtp": "SMTP", "admin.sidebar.smtp": "SMTP",
"admin.sidebar.subscription": "Subscription", "admin.sidebar.subscription": "Subscription",
"admin.sidebar.system_properties": "System Properties", "admin.sidebar.systemAttributes": "System Attributes",
"admin.sidebar.systemRoles": "Delegated Granular Administration", "admin.sidebar.systemRoles": "Delegated Granular Administration",
"admin.sidebar.teams": "Teams", "admin.sidebar.teams": "Teams",
"admin.sidebar.teamStatistics": "Team Statistics", "admin.sidebar.teamStatistics": "Team Statistics",
"admin.sidebar.user_attributes": "User Attributes",
"admin.sidebar.userManagement": "User Management", "admin.sidebar.userManagement": "User Management",
"admin.sidebar.users": "Users", "admin.sidebar.users": "Users",
"admin.sidebar.usersAndTeams": "Users and Teams", "admin.sidebar.usersAndTeams": "Users and Teams",
@@ -2744,15 +2745,15 @@
"admin.support.termsOfServiceTitle": "Custom Terms of Service", "admin.support.termsOfServiceTitle": "Custom Terms of Service",
"admin.support.termsTitle": "Terms of Use Link:", "admin.support.termsTitle": "Terms of Use Link:",
"admin.system_properties.confirm.delete.button": "Delete", "admin.system_properties.confirm.delete.button": "Delete",
"admin.system_properties.confirm.delete.text": "Deleting this property will remove all user-defined values associated with it.", "admin.system_properties.confirm.delete.text": "Deleting this attribute will remove all user-defined values associated with it.",
"admin.system_properties.confirm.delete.title": "Delete {name} property", "admin.system_properties.confirm.delete.title": "Delete {name} attribute",
"admin.system_properties.details.saving_changes": "Saving configuration…", "admin.system_properties.details.saving_changes": "Saving configuration…",
"admin.system_properties.details.saving_changes_error": "There was an error while saving the configuration", "admin.system_properties.details.saving_changes_error": "There was an error while saving the configuration",
"admin.system_properties.user_properties.add_property": "Add property", "admin.system_properties.user_properties.add_property": "Add attribute",
"admin.system_properties.user_properties.dotmenu.ad_ldap.edit_link.label": "Edit link with: <Chip>AD/LDAP: {propertyName}</Chip>", "admin.system_properties.user_properties.dotmenu.ad_ldap.edit_link.label": "Edit link with: <Chip>AD/LDAP: {propertyName}</Chip>",
"admin.system_properties.user_properties.dotmenu.ad_ldap.link_property.label": "Link property to AD/LDAP", "admin.system_properties.user_properties.dotmenu.ad_ldap.link_property.label": "Link attribute to AD/LDAP",
"admin.system_properties.user_properties.dotmenu.delete.label": "Delete property", "admin.system_properties.user_properties.dotmenu.delete.label": "Delete attribute",
"admin.system_properties.user_properties.dotmenu.duplicate.label": "Duplicate property", "admin.system_properties.user_properties.dotmenu.duplicate.label": "Duplicate attribute",
"admin.system_properties.user_properties.dotmenu.duplicate.name_copy": "{fieldName} (copy)", "admin.system_properties.user_properties.dotmenu.duplicate.name_copy": "{fieldName} (copy)",
"admin.system_properties.user_properties.dotmenu.saml.edit_link.label": "Edit link with: <Chip>SAML: {propertyName}</Chip>", "admin.system_properties.user_properties.dotmenu.saml.edit_link.label": "Edit link with: <Chip>SAML: {propertyName}</Chip>",
"admin.system_properties.user_properties.dotmenu.saml.link_property.label": "Link property to SAML", "admin.system_properties.user_properties.dotmenu.saml.link_property.label": "Link property to SAML",
@@ -2760,11 +2761,11 @@
"admin.system_properties.user_properties.dotmenu.visibility.hidden.label": "Always hide", "admin.system_properties.user_properties.dotmenu.visibility.hidden.label": "Always hide",
"admin.system_properties.user_properties.dotmenu.visibility.label": "Visibility", "admin.system_properties.user_properties.dotmenu.visibility.label": "Visibility",
"admin.system_properties.user_properties.dotmenu.visibility.when_set.label": "Hide when empty", "admin.system_properties.user_properties.dotmenu.visibility.when_set.label": "Hide when empty",
"admin.system_properties.user_properties.subtitle": "Customize the properties to show in user profiles", "admin.system_properties.user_properties.subtitle": "Attributes will be shown in user profile and can be used in access control policies.",
"admin.system_properties.user_properties.table.actions": "Actions", "admin.system_properties.user_properties.table.actions": "Actions",
"admin.system_properties.user_properties.table.filter_type": "Property type", "admin.system_properties.user_properties.table.filter_type": "Attribute type",
"admin.system_properties.user_properties.table.property": "Property", "admin.system_properties.user_properties.table.property": "Attribute",
"admin.system_properties.user_properties.table.property_name.input.name": "Property Name", "admin.system_properties.user_properties.table.property_name.input.name": "Attribute Name",
"admin.system_properties.user_properties.table.select_type.email": "Email", "admin.system_properties.user_properties.table.select_type.email": "Email",
"admin.system_properties.user_properties.table.select_type.multi_select": "Multi-select", "admin.system_properties.user_properties.table.select_type.multi_select": "Multi-select",
"admin.system_properties.user_properties.table.select_type.phone": "Phone", "admin.system_properties.user_properties.table.select_type.phone": "Phone",
@@ -2772,16 +2773,16 @@
"admin.system_properties.user_properties.table.select_type.text": "Text", "admin.system_properties.user_properties.table.select_type.text": "Text",
"admin.system_properties.user_properties.table.select_type.url": "URL", "admin.system_properties.user_properties.table.select_type.url": "URL",
"admin.system_properties.user_properties.table.type": "Type", "admin.system_properties.user_properties.table.type": "Type",
"admin.system_properties.user_properties.table.validation.name_required": "Please enter a property name.", "admin.system_properties.user_properties.table.validation.name_required": "Please enter an attribute name.",
"admin.system_properties.user_properties.table.validation.name_taken": "Property name already taken.", "admin.system_properties.user_properties.table.validation.name_taken": "Attribute name already taken.",
"admin.system_properties.user_properties.table.validation.name_unique": "Property names must be unique.", "admin.system_properties.user_properties.table.validation.name_unique": "Attribute names must be unique.",
"admin.system_properties.user_properties.table.validation.values_unique": "Values must be unique.", "admin.system_properties.user_properties.table.validation.values_unique": "Values must be unique.",
"admin.system_properties.user_properties.table.values": "Values", "admin.system_properties.user_properties.table.values": "Values",
"admin.system_properties.user_properties.table.values.placeholder": "Add values… (required)", "admin.system_properties.user_properties.table.values.placeholder": "Add values… (required)",
"admin.system_properties.user_properties.table.values.synced_with": "Synced with: {syncedProperties}", "admin.system_properties.user_properties.table.values.synced_with": "Synced with: {syncedProperties}",
"admin.system_properties.user_properties.table.values.synced_with.ldap": "AD/LDAP: {propertyName}", "admin.system_properties.user_properties.table.values.synced_with.ldap": "AD/LDAP: {propertyName}",
"admin.system_properties.user_properties.table.values.synced_with.saml": "SAML: {propertyName}", "admin.system_properties.user_properties.table.values.synced_with.saml": "SAML: {propertyName}",
"admin.system_properties.user_properties.title": "User Properties", "admin.system_properties.user_properties.title": "Configure user attributes",
"admin.system_roles_feature_discovery.copy": "Assign customizable admin roles to give designated users read and/or write access to select sections of System Console.", "admin.system_roles_feature_discovery.copy": "Assign customizable admin roles to give designated users read and/or write access to select sections of System Console.",
"admin.system_roles_feature_discovery.title": "Provide controlled access to the System Console with Mattermost Enterprise", "admin.system_roles_feature_discovery.title": "Provide controlled access to the System Console with Mattermost Enterprise",
"admin.system_users_list.pagination": "Showing {firstPage} - {lastPage} of {totalItems} users", "admin.system_users_list.pagination": "Showing {firstPage} - {lastPage} of {totalItems} users",

Просмотреть файл

@@ -20,6 +20,10 @@ export const RESOURCE_KEYS = {
PERMISSIONS: 'user_management.permissions', PERMISSIONS: 'user_management.permissions',
SYSTEM_ROLES: 'user_management.system_roles', SYSTEM_ROLES: 'user_management.system_roles',
}, },
SYSTEM_ATTRIBUTES: {
USER_ATTRIBUTES: 'system_attributes.user_attributes',
ATTRIBUTE_BASED_ACCESS_CONTROL: 'system_attributes.attribute_based_access_control',
},
AUTHENTICATION: { AUTHENTICATION: {
SIGNUP: 'authentication.signup', SIGNUP: 'authentication.signup',
EMAIL: 'authentication.email', EMAIL: 'authentication.email',
@@ -93,6 +97,8 @@ export const ResourceToSysConsolePermissionsTable: Record<string, string[]> = {
[RESOURCE_KEYS.USER_MANAGEMENT.CHANNELS]: [Permissions.SYSCONSOLE_READ_USERMANAGEMENT_CHANNELS, Permissions.SYSCONSOLE_WRITE_USERMANAGEMENT_CHANNELS], [RESOURCE_KEYS.USER_MANAGEMENT.CHANNELS]: [Permissions.SYSCONSOLE_READ_USERMANAGEMENT_CHANNELS, Permissions.SYSCONSOLE_WRITE_USERMANAGEMENT_CHANNELS],
[RESOURCE_KEYS.USER_MANAGEMENT.PERMISSIONS]: [Permissions.SYSCONSOLE_READ_USERMANAGEMENT_PERMISSIONS, Permissions.SYSCONSOLE_WRITE_USERMANAGEMENT_PERMISSIONS], [RESOURCE_KEYS.USER_MANAGEMENT.PERMISSIONS]: [Permissions.SYSCONSOLE_READ_USERMANAGEMENT_PERMISSIONS, Permissions.SYSCONSOLE_WRITE_USERMANAGEMENT_PERMISSIONS],
[RESOURCE_KEYS.USER_MANAGEMENT.SYSTEM_ROLES]: [Permissions.SYSCONSOLE_READ_USERMANAGEMENT_SYSTEM_ROLES, Permissions.SYSCONSOLE_WRITE_USERMANAGEMENT_SYSTEM_ROLES], [RESOURCE_KEYS.USER_MANAGEMENT.SYSTEM_ROLES]: [Permissions.SYSCONSOLE_READ_USERMANAGEMENT_SYSTEM_ROLES, Permissions.SYSCONSOLE_WRITE_USERMANAGEMENT_SYSTEM_ROLES],
[RESOURCE_KEYS.SYSTEM_ATTRIBUTES.USER_ATTRIBUTES]: [Permissions.SYSCONSOLE_READ_USERMANAGEMENT_USERS, Permissions.SYSCONSOLE_WRITE_USERMANAGEMENT_USERS],
[RESOURCE_KEYS.SYSTEM_ATTRIBUTES.ATTRIBUTE_BASED_ACCESS_CONTROL]: [Permissions.SYSCONSOLE_READ_USERMANAGEMENT_SYSTEM_ROLES, Permissions.SYSCONSOLE_WRITE_USERMANAGEMENT_SYSTEM_ROLES],
[RESOURCE_KEYS.SITE.CUSTOMIZATION]: [Permissions.SYSCONSOLE_READ_SITE_CUSTOMIZATION, Permissions.SYSCONSOLE_WRITE_SITE_CUSTOMIZATION], [RESOURCE_KEYS.SITE.CUSTOMIZATION]: [Permissions.SYSCONSOLE_READ_SITE_CUSTOMIZATION, Permissions.SYSCONSOLE_WRITE_SITE_CUSTOMIZATION],
[RESOURCE_KEYS.SITE.LOCALIZATION]: [Permissions.SYSCONSOLE_READ_SITE_LOCALIZATION, Permissions.SYSCONSOLE_WRITE_SITE_LOCALIZATION], [RESOURCE_KEYS.SITE.LOCALIZATION]: [Permissions.SYSCONSOLE_READ_SITE_LOCALIZATION, Permissions.SYSCONSOLE_WRITE_SITE_LOCALIZATION],
[RESOURCE_KEYS.SITE.USERS_AND_TEAMS]: [Permissions.SYSCONSOLE_READ_SITE_USERS_AND_TEAMS, Permissions.SYSCONSOLE_WRITE_SITE_USERS_AND_TEAMS], [RESOURCE_KEYS.SITE.USERS_AND_TEAMS]: [Permissions.SYSCONSOLE_READ_SITE_USERS_AND_TEAMS, Permissions.SYSCONSOLE_WRITE_SITE_USERS_AND_TEAMS],

Просмотреть файл

@@ -95,6 +95,7 @@ export function adminDefinitionsToUrlsAndTexts(adminDefinition: typeof AdminDefi
adminDefinition.about, adminDefinition.about,
adminDefinition.reporting, adminDefinition.reporting,
adminDefinition.user_management, adminDefinition.user_management,
adminDefinition.system_attributes,
adminDefinition.environment, adminDefinition.environment,
adminDefinition.site, adminDefinition.site,
adminDefinition.authentication, adminDefinition.authentication,