Remove guest badge (#23825)

* Remove guest badge

* Address feedback

* Fix lint, test and i18n

* Fix test
This commit is contained in:
Daniel Espino García
2023-06-30 11:06:18 +02:00
committed by GitHub
parent 05cd245e97
commit fda5dd8468
18 changed files with 66 additions and 22 deletions

View File

@@ -639,6 +639,7 @@ const defaultServerConfig: AdminConfig = {
},
GuestAccountsSettings: {
Enable: false,
HideTags: false,
AllowEmailAccounts: true,
EnforceMultifactorAuthentication: false,
RestrictCreationToDomains: '',

View File

@@ -322,6 +322,7 @@ func GenerateLimitedClientConfig(c *model.Config, telemetryID string, license *m
props["EnableMultifactorAuthentication"] = strconv.FormatBool(*c.ServiceSettings.EnableMultifactorAuthentication)
props["EnforceMultifactorAuthentication"] = "false"
props["EnableGuestAccounts"] = strconv.FormatBool(*c.GuestAccountsSettings.Enable)
props["HideGuestTags"] = strconv.FormatBool(*c.GuestAccountsSettings.HideTags)
props["GuestAccountsEnforceMultifactorAuthentication"] = strconv.FormatBool(*c.GuestAccountsSettings.EnforceMultifactorAuthentication)
if license != nil {

View File

@@ -860,6 +860,7 @@ func (ts *TelemetryService) trackConfig() {
ts.SendTelemetry(TrackConfigGuestAccounts, map[string]any{
"enable": *cfg.GuestAccountsSettings.Enable,
"hide_tag": *cfg.GuestAccountsSettings.HideTags,
"allow_email_accounts": *cfg.GuestAccountsSettings.AllowEmailAccounts,
"enforce_multifactor_authentication": *cfg.GuestAccountsSettings.EnforceMultifactorAuthentication,
"isdefault_restrict_creation_to_domains": isDefault(*cfg.GuestAccountsSettings.RestrictCreationToDomains, ""),

View File

@@ -3055,6 +3055,7 @@ func (s *DisplaySettings) SetDefaults() {
type GuestAccountsSettings struct {
Enable *bool `access:"authentication_guest_access"`
HideTags *bool `access:"authentication_guest_access"`
AllowEmailAccounts *bool `access:"authentication_guest_access"`
EnforceMultifactorAuthentication *bool `access:"authentication_guest_access"`
RestrictCreationToDomains *string `access:"authentication_guest_access"`
@@ -3065,6 +3066,10 @@ func (s *GuestAccountsSettings) SetDefaults() {
s.Enable = NewBool(false)
}
if s.HideTags == nil {
s.HideTags = NewBool(false)
}
if s.AllowEmailAccounts == nil {
s.AllowEmailAccounts = NewBool(true)
}

View File

@@ -5727,6 +5727,16 @@ const AdminDefinition = {
key: 'GuestAccountsSettings.Enable',
isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.AUTHENTICATION.GUEST_ACCESS)),
},
{
type: Constants.SettingsTypes.TYPE_BOOL,
key: 'GuestAccountsSettings.HideTags',
label: t('admin.guest_access.hideTags'),
label_default: 'Hide guest tag',
help_text: t('admin.guest_access.hideTagsDescription'),
help_text_default: 'When true, the "guest" tag will not be shown next to the name of all guest users in the Mattermost chat interface.',
help_text_markdown: false,
isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.AUTHENTICATION.GUEST_ACCESS)),
},
{
type: Constants.SettingsTypes.TYPE_TEXT,
key: 'GuestAccountsSettings.RestrictCreationToDomains',

View File

@@ -46,6 +46,7 @@ describe('components/ChannelHeader', () => {
'minute',
'hour',
],
hideGuestTags: false,
};
const populatedProps = {

View File

@@ -95,6 +95,7 @@ export type Props = {
isLastActiveEnabled: boolean;
timestampUnits?: string[];
lastActivityTimestamp?: number;
hideGuestTags: boolean;
};
type State = {
@@ -292,12 +293,13 @@ class ChannelHeader extends React.PureComponent<Props, State> {
rhsState,
hasGuests,
teammateNameDisplaySetting,
hideGuestTags,
} = this.props;
const {formatMessage} = this.props.intl;
const ariaLabelChannelHeader = localizeMessage('accessibility.sections.channelHeader', 'channel header region');
let hasGuestsText: ReactNode = '';
if (hasGuests) {
if (hasGuests && !hideGuestTags) {
hasGuestsText = (
<span className='has-guest-header'>
<span tabIndex={0}>
@@ -399,7 +401,7 @@ class ChannelHeader extends React.PureComponent<Props, State> {
);
});
if (hasGuests) {
if (hasGuests && !hideGuestTags) {
hasGuestsText = (
<span className='has-guest-header'>
<FormattedMessage

View File

@@ -116,6 +116,7 @@ function makeMapStateToProps() {
isFileAttachmentsEnabled: isFileAttachmentsEnabled(config),
isLastActiveEnabled,
timestampUnits,
hideGuestTags: config.HideGuestTags === 'true',
};
};
}

View File

@@ -25,6 +25,7 @@ import {Channel} from '@mattermost/types/channels';
import {Post} from '@mattermost/types/posts';
import PostMarkdown from './post_markdown';
import {getConfig} from 'mattermost-redux/selectors/entities/general';
export function makeGetMentionKeysForPost(): (
state: GlobalState,
@@ -75,6 +76,7 @@ function makeMapStateToProps() {
mentionKeys: getMentionKeysForPost(state, ownProps.post, channel),
isMilitaryTime: getBool(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.USE_MILITARY_TIME, false),
timezone: getCurrentTimezone(state),
hideGuestTags: getConfig(state).HideGuestTags === 'true',
};
};
}

View File

@@ -23,6 +23,7 @@ describe('components/PostMarkdown', () => {
channelId: 'channel-id',
channel: TestHelper.getChannelMock(),
currentTeam: TestHelper.getTeamMock(),
hideGuestTags: false,
};
const state = {entities: {

View File

@@ -66,6 +66,8 @@ type Props = {
*/
isMilitaryTime?: boolean;
timezone?: string;
hideGuestTags: boolean;
}
export default class PostMarkdown extends React.PureComponent<Props> {
@@ -94,6 +96,7 @@ export default class PostMarkdown extends React.PureComponent<Props> {
const renderedSystemMessage = renderSystemMessage(post,
this.props.currentTeam,
this.props.channel,
this.props.hideGuestTags,
this.props.isUserCanManageMembers,
this.props.isMilitaryTime,
this.props.timezone);

View File

@@ -50,7 +50,10 @@ function renderJoinChannelMessage(post: Post): ReactNode {
);
}
function renderGuestJoinChannelMessage(post: Post): ReactNode {
function renderGuestJoinChannelMessage(post: Post, hideGuestTags: boolean): ReactNode {
if (hideGuestTags) {
return renderJoinChannelMessage(post);
}
const username = renderUsername(post.props.username);
return (
@@ -90,7 +93,10 @@ function renderAddToChannelMessage(post: Post): ReactNode {
);
}
function renderAddGuestToChannelMessage(post: Post): ReactNode {
function renderAddGuestToChannelMessage(post: Post, hideGuestTags: boolean): ReactNode {
if (hideGuestTags) {
return renderAddToChannelMessage(post);
}
const username = renderUsername(post.props.username);
const addedUsername = renderUsername(post.props.addedUsername);
@@ -363,10 +369,9 @@ function renderMeMessage(post: Post): ReactNode {
const systemMessageRenderers = {
[Posts.POST_TYPES.JOIN_CHANNEL]: renderJoinChannelMessage,
[Posts.POST_TYPES.GUEST_JOIN_CHANNEL]: renderGuestJoinChannelMessage,
[Posts.POST_TYPES.LEAVE_CHANNEL]: renderLeaveChannelMessage,
[Posts.POST_TYPES.ADD_TO_CHANNEL]: renderAddToChannelMessage,
[Posts.POST_TYPES.ADD_GUEST_TO_CHANNEL]: renderAddGuestToChannelMessage,
[Posts.POST_TYPES.EPHEMERAL_ADD_TO_CHANNEL]: renderAddToChannelMessage,
[Posts.POST_TYPES.REMOVE_FROM_CHANNEL]: renderRemoveFromChannelMessage,
[Posts.POST_TYPES.JOIN_TEAM]: renderJoinTeamMessage,
[Posts.POST_TYPES.LEAVE_TEAM]: renderLeaveTeamMessage,
@@ -381,7 +386,7 @@ const systemMessageRenderers = {
[Posts.POST_TYPES.ME]: renderMeMessage,
};
export function renderSystemMessage(post: Post, currentTeam: Team, channel: Channel, isUserCanManageMembers?: boolean, isMilitaryTime?: boolean, timezone?: string): ReactNode {
export function renderSystemMessage(post: Post, currentTeam: Team, channel: Channel, hideGuestTags: boolean, isUserCanManageMembers?: boolean, isMilitaryTime?: boolean, timezone?: string): ReactNode {
const isEphemeral = Utils.isPostEphemeral(post);
if (isEphemeral && post.props?.type === Posts.POST_TYPES.REMINDER) {
return renderReminderACKMessage(post, currentTeam, Boolean(isMilitaryTime), timezone);
@@ -405,8 +410,10 @@ export function renderSystemMessage(post: Post, currentTeam: Team, channel: Chan
return null;
} else if (systemMessageRenderers[post.type]) {
return systemMessageRenderers[post.type](post);
} else if (post.type === Posts.POST_TYPES.EPHEMERAL_ADD_TO_CHANNEL) {
return renderAddToChannelMessage(post);
} else if (post.type === Posts.POST_TYPES.GUEST_JOIN_CHANNEL) {
return renderGuestJoinChannelMessage(post, hideGuestTags);
} else if (post.type === Posts.POST_TYPES.ADD_GUEST_TO_CHANNEL) {
return renderAddGuestToChannelMessage(post, hideGuestTags);
} else if (post.type === Posts.POST_TYPES.COMBINED_USER_ACTIVITY) {
const {allUserIds, allUsernames, messageData} = post.props.user_activity;

View File

@@ -1,9 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/widgets/tag/GuestTag should match the snapshot 1`] = `
<Memo(Tag)
className="GuestTag test"
size="xs"
text="GUEST"
/>
`;

View File

@@ -2,13 +2,18 @@
// See LICENSE.txt for license information.
import React from 'react';
import {shallow} from 'enzyme';
import GuestTag from './guest_tag';
import {renderWithIntlAndStore, screen} from 'tests/react_testing_utils';
describe('components/widgets/tag/GuestTag', () => {
test('should match the snapshot', () => {
const wrapper = shallow(<GuestTag className={'test'}/>);
expect(wrapper).toMatchSnapshot();
renderWithIntlAndStore(<GuestTag className={'test'}/>);
screen.getByText('GUEST');
});
test('should not render when hideTags is true', () => {
renderWithIntlAndStore(<GuestTag className={'test'}/>, {entities: {general: {config: {HideGuestTags: 'true'}}}});
expect(() => screen.getByText('GUEST')).toThrow();
});
});

View File

@@ -6,6 +6,9 @@ import classNames from 'classnames';
import {useIntl} from 'react-intl';
import Tag, {TagSize} from './tag';
import {useSelector} from 'react-redux';
import {getConfig} from 'mattermost-redux/selectors/entities/general';
import {GlobalState} from '@mattermost/types/store';
type Props = {
className?: string;
@@ -14,6 +17,12 @@ type Props = {
const GuestTag = ({className = '', size = 'xs'}: Props) => {
const {formatMessage} = useIntl();
const shouldHideTag = useSelector((state: GlobalState) => getConfig(state).HideGuestTags === 'true');
if (shouldHideTag) {
return null;
}
return (
<Tag
className={classNames('GuestTag', className)}

View File

@@ -1127,6 +1127,8 @@
"admin.guest_access.disableConfirmWarning": "All current guest account sessions will be revoked, and marked as inactive",
"admin.guest_access.enableDescription": "When true, external guest can be invited to channels within teams. Please see [Permissions Schemes](../user_management/permissions/system_scheme) for which roles can invite guests.",
"admin.guest_access.enableTitle": "Enable Guest Access: ",
"admin.guest_access.hideTags": "Hide guest tag",
"admin.guest_access.hideTagsDescription": "When true, the \"guest\" tag will not be shown next to the name of all guest users in the Mattermost chat interface.",
"admin.guest_access.mfaDescription": "When true, <link>multi-factor authentication</link> for guests is required for login. New guest users will be required to configure MFA on signup. Logged in guest users without MFA configured are redirected to the MFA setup page until configuration is complete.\n \nIf your system has guest users with login methods other than AD/LDAP and email, MFA must be enforced with the authentication provider outside of Mattermost.",
"admin.guest_access.mfaDescriptionMFANotEnabled": "[Multi-factor authentication](./mfa) is currently not enabled.",
"admin.guest_access.mfaDescriptionMFANotEnforced": "[Multi-factor authentication](./mfa) is currently not enforced.",

View File

@@ -26,7 +26,7 @@ export const renderWithIntl = (component: React.ReactNode | React.ReactNodeArray
return render(<IntlProvider locale={locale}>{component}</IntlProvider>);
};
export const renderWithIntlAndStore = (component: React.ReactNode | React.ReactNodeArray, initialState: DeepPartial<GlobalState>, locale = 'en') => {
export const renderWithIntlAndStore = (component: React.ReactNode | React.ReactNodeArray, initialState: DeepPartial<GlobalState> = {}, locale = 'en') => {
// We use a redux-mock-store store for testing, but we set up a real store to ensure the initial state is complete
const realStore = configureStore(initialState);

View File

@@ -127,6 +127,7 @@ export type ClientConfig = {
GuestAccountsEnforceMultifactorAuthentication: string;
HasImageProxy: string;
HelpLink: string;
HideGuestTags: string;
IosAppDownloadLink: string;
IosLatestVersion: string;
IosMinVersion: string;
@@ -846,6 +847,7 @@ export type DisplaySettings = {
export type GuestAccountsSettings = {
Enable: boolean;
HideTags: boolean;
AllowEmailAccounts: boolean;
EnforceMultifactorAuthentication: boolean;
RestrictCreationToDomains: string;