[MM-53124] Add optional Forgot Password custom link to override the default flow on the login page (#23831)
* [MM-53124] Add optional Forgot Password custom link to override the default flow on the login page * Fix i18n * Fix test * Added the enable/disable flag * Fix test * Fix e2e * Add blockable link for the Customization navigation
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
b59cba7e63
Коммит
116728424c
@@ -44,6 +44,7 @@ const onPremServerConfig = (): Partial<TestAdminConfig> => {
|
||||
Number: false,
|
||||
Uppercase: false,
|
||||
Symbol: false,
|
||||
EnableForgotLink: true,
|
||||
},
|
||||
PluginSettings: {
|
||||
EnableUploads: true,
|
||||
@@ -265,6 +266,7 @@ const defaultServerConfig: AdminConfig = {
|
||||
Number: false,
|
||||
Uppercase: false,
|
||||
Symbol: false,
|
||||
EnableForgotLink: true,
|
||||
},
|
||||
FileSettings: {
|
||||
EnableFileAttachments: true,
|
||||
@@ -345,6 +347,7 @@ const defaultServerConfig: AdminConfig = {
|
||||
AboutLink: 'https://docs.mattermost.com/pl/about-mattermost',
|
||||
HelpLink: 'https://mattermost.com/pl/help/',
|
||||
ReportAProblemLink: 'https://mattermost.com/pl/report-a-bug',
|
||||
ForgotPasswordLink: '',
|
||||
SupportEmail: '',
|
||||
CustomTermsOfServiceEnabled: false,
|
||||
CustomTermsOfServiceReAcceptancePeriod: 365,
|
||||
|
||||
@@ -272,6 +272,7 @@ func GenerateLimitedClientConfig(c *model.Config, telemetryID string, license *m
|
||||
props["AboutLink"] = *c.SupportSettings.AboutLink
|
||||
props["HelpLink"] = *c.SupportSettings.HelpLink
|
||||
props["ReportAProblemLink"] = *c.SupportSettings.ReportAProblemLink
|
||||
props["ForgotPasswordLink"] = *c.SupportSettings.ForgotPasswordLink
|
||||
props["SupportEmail"] = *c.SupportSettings.SupportEmail
|
||||
props["EnableAskCommunityLink"] = strconv.FormatBool(*c.SupportSettings.EnableAskCommunityLink)
|
||||
|
||||
@@ -295,6 +296,7 @@ func GenerateLimitedClientConfig(c *model.Config, telemetryID string, license *m
|
||||
props["PasswordRequireUppercase"] = strconv.FormatBool(*c.PasswordSettings.Uppercase)
|
||||
props["PasswordRequireNumber"] = strconv.FormatBool(*c.PasswordSettings.Number)
|
||||
props["PasswordRequireSymbol"] = strconv.FormatBool(*c.PasswordSettings.Symbol)
|
||||
props["PasswordEnableForgotLink"] = strconv.FormatBool(*c.PasswordSettings.EnableForgotLink)
|
||||
|
||||
// Set default values for all options that require a license.
|
||||
props["EnableCustomBrand"] = "false"
|
||||
|
||||
@@ -1487,11 +1487,12 @@ func (s *NotificationLogSettings) GetAdvancedLoggingConfig() []byte {
|
||||
}
|
||||
|
||||
type PasswordSettings struct {
|
||||
MinimumLength *int `access:"authentication_password"`
|
||||
Lowercase *bool `access:"authentication_password"`
|
||||
Number *bool `access:"authentication_password"`
|
||||
Uppercase *bool `access:"authentication_password"`
|
||||
Symbol *bool `access:"authentication_password"`
|
||||
MinimumLength *int `access:"authentication_password"`
|
||||
Lowercase *bool `access:"authentication_password"`
|
||||
Number *bool `access:"authentication_password"`
|
||||
Uppercase *bool `access:"authentication_password"`
|
||||
Symbol *bool `access:"authentication_password"`
|
||||
EnableForgotLink *bool `access:"authentication_password"`
|
||||
}
|
||||
|
||||
func (s *PasswordSettings) SetDefaults() {
|
||||
@@ -1514,6 +1515,10 @@ func (s *PasswordSettings) SetDefaults() {
|
||||
if s.Symbol == nil {
|
||||
s.Symbol = NewBool(false)
|
||||
}
|
||||
|
||||
if s.EnableForgotLink == nil {
|
||||
s.EnableForgotLink = NewBool(true)
|
||||
}
|
||||
}
|
||||
|
||||
type FileSettings struct {
|
||||
@@ -1882,6 +1887,7 @@ type SupportSettings struct {
|
||||
AboutLink *string `access:"site_customization,write_restrictable,cloud_restrictable"`
|
||||
HelpLink *string `access:"site_customization"`
|
||||
ReportAProblemLink *string `access:"site_customization,write_restrictable,cloud_restrictable"`
|
||||
ForgotPasswordLink *string `access:"site_customization,write_restrictable,cloud_restrictable"`
|
||||
SupportEmail *string `access:"site_notifications"`
|
||||
CustomTermsOfServiceEnabled *bool `access:"compliance_custom_terms_of_service"`
|
||||
CustomTermsOfServiceReAcceptancePeriod *int `access:"compliance_custom_terms_of_service"`
|
||||
@@ -1929,6 +1935,14 @@ func (s *SupportSettings) SetDefaults() {
|
||||
s.ReportAProblemLink = NewString(SupportSettingsDefaultReportAProblemLink)
|
||||
}
|
||||
|
||||
if !isSafeLink(s.ForgotPasswordLink) {
|
||||
*s.ForgotPasswordLink = ""
|
||||
}
|
||||
|
||||
if s.ForgotPasswordLink == nil {
|
||||
s.ForgotPasswordLink = NewString("")
|
||||
}
|
||||
|
||||
if s.SupportEmail == nil {
|
||||
s.SupportEmail = NewString(SupportSettingsDefaultSupportEmail)
|
||||
}
|
||||
|
||||
@@ -115,7 +115,8 @@
|
||||
"Lowercase": false,
|
||||
"Number": false,
|
||||
"Uppercase": false,
|
||||
"Symbol": false
|
||||
"Symbol": false,
|
||||
"EnableForgotLink": true
|
||||
},
|
||||
"FileSettings": {
|
||||
"EnableFileAttachments": true,
|
||||
@@ -187,6 +188,7 @@
|
||||
"AboutLink": "https://mattermost.com/default-about/",
|
||||
"HelpLink": "https://mattermost.com/pl/help/",
|
||||
"ReportAProblemLink": "https://mattermost.com/pl/report-a-bug",
|
||||
"ForgotPasswordLink": "",
|
||||
"SupportEmail": "feedback@mattermost.com"
|
||||
},
|
||||
"AnnouncementSettings": {
|
||||
|
||||
@@ -55,7 +55,7 @@ import TeamSettings from './team_channel_settings/team';
|
||||
import TeamDetails from './team_channel_settings/team/details';
|
||||
import ChannelSettings from './team_channel_settings/channel';
|
||||
import ChannelDetails from './team_channel_settings/channel/details';
|
||||
import PasswordSettings from './password_settings.jsx';
|
||||
import PasswordSettings from './password_settings';
|
||||
import PushNotificationsSettings from './push_settings';
|
||||
import DataRetentionSettings from './data_retention_settings';
|
||||
import GlobalDataRetentionForm from './data_retention_settings/global_policy_form';
|
||||
@@ -2135,6 +2135,16 @@ const AdminDefinition = {
|
||||
isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.SITE.CUSTOMIZATION)),
|
||||
isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
|
||||
},
|
||||
{
|
||||
type: Constants.SettingsTypes.TYPE_TEXT,
|
||||
key: 'SupportSettings.ForgotPasswordLink',
|
||||
label: t('admin.support.forgotPasswordTitle'),
|
||||
label_default: 'Forgot Password Custom Link:',
|
||||
help_text: t('admin.support.forgotPasswordDesc'),
|
||||
help_text_default: 'The URL for the Forgot Password link on the Mattermost login page. If this field is empty the Forgot Password link takes users to the Password Reset page.',
|
||||
isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.SITE.CUSTOMIZATION)),
|
||||
isHidden: it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'),
|
||||
},
|
||||
{
|
||||
type: Constants.SettingsTypes.TYPE_TEXT,
|
||||
key: 'SupportSettings.ReportAProblemLink',
|
||||
|
||||
@@ -4,17 +4,38 @@
|
||||
import React from 'react';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
|
||||
import {AdminConfig} from '@mattermost/types/config';
|
||||
import {DeepPartial} from '@mattermost/types/utilities';
|
||||
|
||||
import Constants from 'utils/constants';
|
||||
import * as Utils from 'utils/utils';
|
||||
import {t} from 'utils/i18n';
|
||||
|
||||
import AdminSettings from './admin_settings';
|
||||
import AdminSettings, {BaseProps, BaseState} from './admin_settings';
|
||||
import BooleanSetting from './boolean_setting';
|
||||
import Setting from './setting';
|
||||
import SettingsGroup from './settings_group';
|
||||
import TextSetting from './text_setting';
|
||||
import BlockableLink from './blockable_link';
|
||||
|
||||
export default class PasswordSettings extends AdminSettings {
|
||||
constructor(props) {
|
||||
type Props = BaseProps & {
|
||||
config: AdminConfig;
|
||||
};
|
||||
|
||||
type State = BaseState & {
|
||||
passwordMinimumLength?: string;
|
||||
passwordLowercase?: boolean;
|
||||
passwordNumber?: boolean;
|
||||
passwordUppercase?: boolean;
|
||||
passwordSymbol?: boolean;
|
||||
passwordEnableForgotLink?: boolean;
|
||||
maximumLoginAttempts?: string;
|
||||
};
|
||||
|
||||
export default class PasswordSettings extends AdminSettings<Props, State> {
|
||||
sampleErrorMsg: React.ReactNode;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = Object.assign(this.state, {
|
||||
@@ -23,6 +44,7 @@ export default class PasswordSettings extends AdminSettings {
|
||||
passwordNumber: props.config.PasswordSettings.Number,
|
||||
passwordUppercase: props.config.PasswordSettings.Uppercase,
|
||||
passwordSymbol: props.config.PasswordSettings.Symbol,
|
||||
passwordEnableForgotLink: props.config.PasswordSettings.EnableForgotLink,
|
||||
maximumLoginAttempts: props.config.ServiceSettings.MaximumLoginAttempts,
|
||||
});
|
||||
|
||||
@@ -59,7 +81,7 @@ export default class PasswordSettings extends AdminSettings {
|
||||
this.sampleErrorMsg = (
|
||||
<FormattedMessage
|
||||
id={sampleErrorMsgId}
|
||||
default='Your password must contain between {min} and {max} characters.'
|
||||
defaultMessage='Your password must contain between {min} and {max} characters.'
|
||||
values={{
|
||||
min: (this.state.passwordMinimumLength || Constants.MIN_PASSWORD_LENGTH),
|
||||
max: Constants.MAX_PASSWORD_LENGTH,
|
||||
@@ -68,26 +90,32 @@ export default class PasswordSettings extends AdminSettings {
|
||||
);
|
||||
}
|
||||
|
||||
getConfigFromState = (config) => {
|
||||
config.PasswordSettings.MinimumLength = this.parseIntNonZero(this.state.passwordMinimumLength, Constants.MIN_PASSWORD_LENGTH);
|
||||
config.PasswordSettings.Lowercase = this.state.passwordLowercase;
|
||||
config.PasswordSettings.Uppercase = this.state.passwordUppercase;
|
||||
config.PasswordSettings.Number = this.state.passwordNumber;
|
||||
config.PasswordSettings.Symbol = this.state.passwordSymbol;
|
||||
getConfigFromState = (config: DeepPartial<AdminConfig>) => {
|
||||
if (config.PasswordSettings) {
|
||||
config.PasswordSettings.MinimumLength = this.parseIntNonZero(this.state.passwordMinimumLength ?? '', Constants.MIN_PASSWORD_LENGTH);
|
||||
config.PasswordSettings.Lowercase = this.state.passwordLowercase;
|
||||
config.PasswordSettings.Uppercase = this.state.passwordUppercase;
|
||||
config.PasswordSettings.Number = this.state.passwordNumber;
|
||||
config.PasswordSettings.Symbol = this.state.passwordSymbol;
|
||||
config.PasswordSettings.EnableForgotLink = this.state.passwordEnableForgotLink;
|
||||
}
|
||||
|
||||
config.ServiceSettings.MaximumLoginAttempts = this.parseIntNonZero(this.state.maximumLoginAttempts, Constants.MAXIMUM_LOGIN_ATTEMPTS_DEFAULT);
|
||||
if (config.ServiceSettings) {
|
||||
config.ServiceSettings.MaximumLoginAttempts = this.parseIntNonZero(this.state.maximumLoginAttempts ?? '', Constants.MAXIMUM_LOGIN_ATTEMPTS_DEFAULT);
|
||||
}
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
getStateFromConfig(config) {
|
||||
getStateFromConfig(config: DeepPartial<AdminConfig>) {
|
||||
return {
|
||||
passwordMinimumLength: config.PasswordSettings.MinimumLength,
|
||||
passwordLowercase: config.PasswordSettings.Lowercase,
|
||||
passwordNumber: config.PasswordSettings.Number,
|
||||
passwordUppercase: config.PasswordSettings.Uppercase,
|
||||
passwordSymbol: config.PasswordSettings.Symbol,
|
||||
maximumLoginAttempts: config.ServiceSettings.MaximumLoginAttempts,
|
||||
passwordMinimumLength: String(config.PasswordSettings?.MinimumLength),
|
||||
passwordLowercase: config.PasswordSettings?.Lowercase,
|
||||
passwordNumber: config.PasswordSettings?.Number,
|
||||
passwordUppercase: config.PasswordSettings?.Uppercase,
|
||||
passwordSymbol: config.PasswordSettings?.Symbol,
|
||||
passwordEnableForgotLink: config.PasswordSettings?.EnableForgotLink,
|
||||
maximumLoginAttempts: String(config.ServiceSettings?.MaximumLoginAttempts),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -96,7 +124,7 @@ export default class PasswordSettings extends AdminSettings {
|
||||
return (
|
||||
<FormattedMessage
|
||||
id='user.settings.security.passwordMinLength'
|
||||
default='Invalid minimum length, cannot show preview.'
|
||||
defaultMessage='Invalid minimum length, cannot show preview.'
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -116,7 +144,7 @@ export default class PasswordSettings extends AdminSettings {
|
||||
return (
|
||||
<FormattedMessage
|
||||
id={sampleErrorMsgId}
|
||||
default='Your password must contain between {min} and {max} characters.'
|
||||
defaultMessage='Your password must contain between {min} and {max} characters.'
|
||||
values={{
|
||||
min: (this.state.passwordMinimumLength || Constants.MIN_PASSWORD_LENGTH),
|
||||
max: Constants.MAX_PASSWORD_LENGTH,
|
||||
@@ -125,13 +153,9 @@ export default class PasswordSettings extends AdminSettings {
|
||||
);
|
||||
};
|
||||
|
||||
handlePasswordLengthChange = (id, value) => {
|
||||
this.handleChange(id, value);
|
||||
};
|
||||
|
||||
handleCheckboxChange = (id) => {
|
||||
return ({target: {checked}}) => {
|
||||
this.handleChange(id, checked);
|
||||
handleCheckboxChange = (id: string) => {
|
||||
return (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
this.handleChange(id, event.target.checked);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -167,10 +191,11 @@ export default class PasswordSettings extends AdminSettings {
|
||||
}}
|
||||
/>
|
||||
}
|
||||
value={this.state.passwordMinimumLength}
|
||||
onChange={this.handlePasswordLengthChange}
|
||||
value={this.state.passwordMinimumLength ?? ''}
|
||||
onChange={this.handleChange}
|
||||
setByEnv={this.isSetByEnv('PasswordSettings.MinimumLength')}
|
||||
disabled={this.props.isDisabled}
|
||||
type='input'
|
||||
/>
|
||||
<Setting
|
||||
label={
|
||||
@@ -184,7 +209,6 @@ export default class PasswordSettings extends AdminSettings {
|
||||
<label className='checkbox-inline'>
|
||||
<input
|
||||
type='checkbox'
|
||||
ref={this.lowercase}
|
||||
defaultChecked={this.state.passwordLowercase}
|
||||
name='admin.password.lowercase'
|
||||
disabled={this.props.isDisabled}
|
||||
@@ -200,7 +224,6 @@ export default class PasswordSettings extends AdminSettings {
|
||||
<label className='checkbox-inline'>
|
||||
<input
|
||||
type='checkbox'
|
||||
ref={this.uppercase}
|
||||
defaultChecked={this.state.passwordUppercase}
|
||||
name='admin.password.uppercase'
|
||||
disabled={this.props.isDisabled}
|
||||
@@ -216,7 +239,6 @@ export default class PasswordSettings extends AdminSettings {
|
||||
<label className='checkbox-inline'>
|
||||
<input
|
||||
type='checkbox'
|
||||
ref={this.number}
|
||||
defaultChecked={this.state.passwordNumber}
|
||||
name='admin.password.number'
|
||||
disabled={this.props.isDisabled}
|
||||
@@ -232,7 +254,6 @@ export default class PasswordSettings extends AdminSettings {
|
||||
<label className='checkbox-inline'>
|
||||
<input
|
||||
type='checkbox'
|
||||
ref={this.symbol}
|
||||
defaultChecked={this.state.passwordSymbol}
|
||||
name='admin.password.symbol'
|
||||
disabled={this.props.isDisabled}
|
||||
@@ -274,13 +295,40 @@ export default class PasswordSettings extends AdminSettings {
|
||||
defaultMessage='Login attempts allowed before user is locked out and required to reset password via email.'
|
||||
/>
|
||||
}
|
||||
value={this.state.maximumLoginAttempts}
|
||||
value={this.state.maximumLoginAttempts ?? ''}
|
||||
onChange={this.handleChange}
|
||||
setByEnv={this.isSetByEnv('ServiceSettings.MaximumLoginAttempts')}
|
||||
disabled={this.props.isDisabled}
|
||||
type='input'
|
||||
/>
|
||||
)
|
||||
}
|
||||
<BooleanSetting
|
||||
id='passwordEnableForgotLink'
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='admin.password.enableForgotLink.title'
|
||||
defaultMessage='Enable Forgot Password Link:'
|
||||
/>
|
||||
}
|
||||
helpText={
|
||||
<FormattedMessage
|
||||
id='admin.password.enableForgotLink.description'
|
||||
defaultMessage='When true, “Forgot password” link appears on the Mattermost login page, which allows users to reset their password. When false, the link is hidden from users. This link can be customized to redirect to a URL of your choice from <a>Site Configuration > Customization.</a>'
|
||||
values={{
|
||||
a: (chunks) => (
|
||||
<BlockableLink to='/admin_console/site_config/customization'>
|
||||
{chunks}
|
||||
</BlockableLink>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
}
|
||||
value={this.state.passwordEnableForgotLink ?? false}
|
||||
setByEnv={false}
|
||||
onChange={this.handleChange}
|
||||
disabled={this.props.isDisabled}
|
||||
/>
|
||||
</SettingsGroup>
|
||||
);
|
||||
};
|
||||
@@ -125,6 +125,7 @@ describe('components/login/Login', () => {
|
||||
CustomDescriptionText: '',
|
||||
SiteName: 'Mattermost',
|
||||
ExperimentalPrimaryTeam: '',
|
||||
PasswordEnableForgotLink: 'true',
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ import {setCSRFFromCookie} from 'utils/utils';
|
||||
import LoginMfa from './login_mfa';
|
||||
|
||||
import './login.scss';
|
||||
import ExternalLink from 'components/external_link';
|
||||
|
||||
const MOBILE_SCREEN_WIDTH = 1200;
|
||||
|
||||
@@ -98,6 +99,8 @@ const Login = ({onCustomizeHeader}: LoginProps) => {
|
||||
CustomDescriptionText,
|
||||
SiteName,
|
||||
ExperimentalPrimaryTeam,
|
||||
ForgotPasswordLink,
|
||||
PasswordEnableForgotLink,
|
||||
} = useSelector(getConfig);
|
||||
const {IsLicensed} = useSelector(getLicense);
|
||||
const initializing = useSelector((state: GlobalState) => state.requests.users.logout.status === RequestStatus.SUCCESS || !state.storage.initialized);
|
||||
@@ -703,6 +706,34 @@ const Login = ({onCustomizeHeader}: LoginProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
const getResetPasswordLink = () => {
|
||||
if (!PasswordEnableForgotLink || PasswordEnableForgotLink === 'false') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (ForgotPasswordLink) {
|
||||
return (
|
||||
<div className='login-body-card-form-link'>
|
||||
<ExternalLink href={ForgotPasswordLink}>
|
||||
{formatMessage({id: 'login.forgot', defaultMessage: 'Forgot your password?'})}
|
||||
</ExternalLink>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (enableSignInWithUsername || enableSignInWithEmail) {
|
||||
return (
|
||||
<div className='login-body-card-form-link'>
|
||||
<Link to='/reset_password'>
|
||||
{formatMessage({id: 'login.forgot', defaultMessage: 'Forgot your password?'})}
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const getContent = () => {
|
||||
if (showMfa) {
|
||||
return (
|
||||
@@ -802,13 +833,7 @@ const Login = ({onCustomizeHeader}: LoginProps) => {
|
||||
hasError={hasError}
|
||||
disabled={isWaiting}
|
||||
/>
|
||||
{(enableSignInWithUsername || enableSignInWithEmail) && (
|
||||
<div className='login-body-card-form-link'>
|
||||
<Link to='/reset_password'>
|
||||
{formatMessage({id: 'login.forgot', defaultMessage: 'Forgot your password?'})}
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
{getResetPasswordLink()}
|
||||
<SaveButton
|
||||
extraClasses='login-body-card-form-button-submit large'
|
||||
saving={isWaiting}
|
||||
|
||||
@@ -1505,6 +1505,8 @@
|
||||
"admin.openIdConvert.help": "Learn more",
|
||||
"admin.openIdConvert.message": "You can now convert your OAuth2.0 configuration to OpenID Connect.",
|
||||
"admin.openIdConvert.text": "Convert to OpenID Connect",
|
||||
"admin.password.enableForgotLink.description": "When true, “Forgot password” link appears on the Mattermost login page, which allows users to reset their password. When false, the link is hidden from users. This link can be customized to redirect to a URL of your choice from <a>Site Configuration > Customization.</a>",
|
||||
"admin.password.enableForgotLink.title": "Enable Forgot Password Link:",
|
||||
"admin.password.lowercase": "At least one lowercase letter",
|
||||
"admin.password.minimumLength": "Minimum Password Length:",
|
||||
"admin.password.minimumLengthDescription": "Minimum number of characters required for a valid password. Must be a whole number greater than or equal to {min} and less than or equal to {max}.",
|
||||
@@ -2357,6 +2359,8 @@
|
||||
"admin.support.enableAskCommunityTitle": "Enable Ask Community Link:",
|
||||
"admin.support.enableTermsOfServiceHelp": "When true, new users must accept the terms of service before accessing any Mattermost teams on desktop, web or mobile. Existing users must accept them after login or a page refresh.\n \nTo update terms of service link displayed in account creation and login pages, go to [Site Configuration > Customization](../site_config/customization).",
|
||||
"admin.support.enableTermsOfServiceTitle": "Enable Custom Terms of Service:",
|
||||
"admin.support.forgotPasswordDesc": "The URL for the Forgot Password link on the Mattermost login page. If this field is empty the Forgot Password link takes users to the Password Reset page.",
|
||||
"admin.support.forgotPasswordTitle": "Forgot Password Custom Link:",
|
||||
"admin.support.helpDesc": "The URL for the Help link on the Mattermost login page, sign-up pages, and Help Menu. If this field is empty, the Help link is hidden from users.",
|
||||
"admin.support.helpTitle": "Help Link:",
|
||||
"admin.support.privacyDesc": "The URL for the Privacy link on the login and sign-up pages. If this field is empty, the Privacy link is hidden from users.",
|
||||
|
||||
@@ -121,6 +121,7 @@ export type ClientConfig = {
|
||||
FeatureFlagBoardsProduct: string;
|
||||
FeatureFlagCallsEnabled: string;
|
||||
FeatureFlagGraphQL: string;
|
||||
ForgotPasswordLink: string;
|
||||
GfycatAPIKey: string;
|
||||
GfycatAPISecret: string;
|
||||
GoogleDeveloperKey: string;
|
||||
@@ -154,6 +155,7 @@ export type ClientConfig = {
|
||||
GitLabButtonColor: string;
|
||||
OpenIdButtonText: string;
|
||||
OpenIdButtonColor: string;
|
||||
PasswordEnableForgotLink: string;
|
||||
PasswordMinimumLength: string;
|
||||
PasswordRequireLowercase: string;
|
||||
PasswordRequireNumber: string;
|
||||
@@ -477,6 +479,7 @@ export type PasswordSettings = {
|
||||
Number: boolean;
|
||||
Uppercase: boolean;
|
||||
Symbol: boolean;
|
||||
EnableForgotLink: boolean;
|
||||
};
|
||||
|
||||
export type FileSettings = {
|
||||
@@ -562,6 +565,7 @@ export type SupportSettings = {
|
||||
AboutLink: string;
|
||||
HelpLink: string;
|
||||
ReportAProblemLink: string;
|
||||
ForgotPasswordLink: string;
|
||||
SupportEmail: string;
|
||||
CustomTermsOfServiceEnabled: boolean;
|
||||
CustomTermsOfServiceReAcceptancePeriod: number;
|
||||
|
||||
Ссылка в новой задаче
Block a user