Merge pull request #376 from ONLYOFFICE/bugfix/profile-form-validation
Bugfix/profile form validation
This commit is contained in:
commit
596ff52ed4
@ -92,6 +92,9 @@ class SettingsStore {
|
||||
};
|
||||
debugInfo = false;
|
||||
|
||||
userFormValidation = /^[\p{L}\p{M}'\-]+$/gu;
|
||||
folderFormValidation = new RegExp('[*+:"<>?|\\\\/]', "gim");
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
@ -182,15 +182,15 @@ export default function withContent(WrappedContent) {
|
||||
};
|
||||
|
||||
renameTitle = (e) => {
|
||||
const { t } = this.props;
|
||||
const { t, folderFormValidation } = this.props;
|
||||
|
||||
let title = e.target.value;
|
||||
//const chars = '*+:"<>?|/'; TODO: think how to solve problem with interpolation escape values in i18n translate
|
||||
const regexp = new RegExp('[*+:"<>?|\\\\/]', "gim");
|
||||
if (title.match(regexp)) {
|
||||
|
||||
if (title.match(folderFormValidation)) {
|
||||
toastr.warning(t("ContainsSpecCharacter"));
|
||||
}
|
||||
title = title.replace(regexp, "_");
|
||||
title = title.replace(folderFormValidation, "_");
|
||||
return this.setState({ itemTitle: title });
|
||||
};
|
||||
|
||||
@ -324,7 +324,11 @@ export default function withContent(WrappedContent) {
|
||||
id: fileActionId,
|
||||
} = filesStore.fileActionStore;
|
||||
const { replaceFileStream, setEncryptionAccess } = auth;
|
||||
const { culture, isDesktopClient } = auth.settingsStore;
|
||||
const {
|
||||
culture,
|
||||
isDesktopClient,
|
||||
folderFormValidation,
|
||||
} = auth.settingsStore;
|
||||
|
||||
return {
|
||||
setIsLoading,
|
||||
@ -346,6 +350,7 @@ export default function withContent(WrappedContent) {
|
||||
homepage: config.homepage,
|
||||
viewer: auth.userStore.user,
|
||||
viewAs,
|
||||
folderFormValidation,
|
||||
};
|
||||
}
|
||||
)(observer(WithContent));
|
||||
|
@ -29,6 +29,7 @@ const PureConnectDialogContainer = (props) => {
|
||||
setConnectDialogVisible,
|
||||
personal,
|
||||
getSubfolders,
|
||||
folderFormValidation,
|
||||
} = props;
|
||||
const {
|
||||
corporate,
|
||||
@ -80,12 +81,11 @@ const PureConnectDialogContainer = (props) => {
|
||||
setIsTitleValid(true);
|
||||
let title = e.target.value;
|
||||
//const chars = '*+:"<>?|/'; TODO: think how to solve problem with interpolation escape values in i18n translate
|
||||
const regexp = new RegExp('[*+:"<>?|\\\\/]', "gim");
|
||||
|
||||
if (title.match(regexp)) {
|
||||
if (title.match(folderFormValidation)) {
|
||||
toastr.warning(t("Home:ContainsSpecCharacter"));
|
||||
}
|
||||
title = title.replace(regexp, "_");
|
||||
title = title.replace(folderFormValidation, "_");
|
||||
|
||||
setCustomerTitleValue(title);
|
||||
};
|
||||
@ -340,7 +340,11 @@ export default inject(
|
||||
openConnectWindow,
|
||||
fetchThirdPartyProviders,
|
||||
} = settingsStore.thirdPartyStore;
|
||||
const { getOAuthToken, personal } = auth.settingsStore;
|
||||
const {
|
||||
getOAuthToken,
|
||||
personal,
|
||||
folderFormValidation,
|
||||
} = auth.settingsStore;
|
||||
|
||||
const {
|
||||
treeFolders,
|
||||
@ -364,6 +368,7 @@ export default inject(
|
||||
providers,
|
||||
visible,
|
||||
item,
|
||||
folderFormValidation,
|
||||
|
||||
getOAuthToken,
|
||||
getSubfolders,
|
||||
|
@ -19,5 +19,7 @@
|
||||
"TemporaryPassword": "Vorübergehendes Kennwort",
|
||||
"TermsOfUsePopupHelperLink": "Erfahren Sie mehr über die Nutzungsbedingungen",
|
||||
"UpdatingProcess": "Wird aktualisiert...",
|
||||
"WriteComment": "Kommentar hinzufügen"
|
||||
"WriteComment": "Kommentar hinzufügen",
|
||||
"ErrorInvalidUserLastName": "Ungültiger Nachname",
|
||||
"ErrorInvalidUserFirstName": "Ungültiger Vorname"
|
||||
}
|
||||
|
@ -20,5 +20,7 @@
|
||||
"TemporaryPassword": "Temporary password",
|
||||
"TermsOfUsePopupHelperLink": "Read more about terms of use",
|
||||
"UpdatingProcess": "Updating...",
|
||||
"WriteComment": "Add comment"
|
||||
"WriteComment": "Add comment",
|
||||
"ErrorInvalidUserLastName": "Invalid last name",
|
||||
"ErrorInvalidUserFirstName": "Invalid first name"
|
||||
}
|
||||
|
@ -19,5 +19,7 @@
|
||||
"TemporaryPassword": "Mot de passe temporaire",
|
||||
"TermsOfUsePopupHelperLink": "Savoir plus à propos de termes d'utilisation ",
|
||||
"UpdatingProcess": "Mis à jour...",
|
||||
"WriteComment": "Ajouter un commentaire"
|
||||
"WriteComment": "Ajouter un commentaire",
|
||||
"ErrorInvalidUserLastName": "Prénom invalide",
|
||||
"ErrorInvalidUserFirstName": "Nom invalide"
|
||||
}
|
||||
|
@ -19,5 +19,7 @@
|
||||
"TemporaryPassword": "Password temporanea",
|
||||
"TermsOfUsePopupHelperLink": "Maggiori dettagli sui termini di utilizzo",
|
||||
"UpdatingProcess": "Caricamento in corso...",
|
||||
"WriteComment": "Aggiungi commento"
|
||||
"WriteComment": "Aggiungi commento",
|
||||
"ErrorInvalidUserLastName": "Cognome non valido",
|
||||
"ErrorInvalidUserFirstName": "Nome non valido"
|
||||
}
|
||||
|
@ -19,5 +19,7 @@
|
||||
"TemporaryPassword": "Senha temporária",
|
||||
"TermsOfUsePopupHelperLink": "Leia mais sobre os termos de uso",
|
||||
"UpdatingProcess": "Atualizando...",
|
||||
"WriteComment": "Adicionar comentário"
|
||||
"WriteComment": "Adicionar comentário",
|
||||
"ErrorInvalidUserLastName": "Sobrenome inválido",
|
||||
"ErrorInvalidUserFirstName": "Primeiro nome inválido"
|
||||
}
|
||||
|
@ -20,5 +20,7 @@
|
||||
"TemporaryPassword": "Временный пароль",
|
||||
"TermsOfUsePopupHelperLink": "Подробнее об условиях использования",
|
||||
"UpdatingProcess": "Обновление...",
|
||||
"WriteComment": "Добавить комментарий"
|
||||
"WriteComment": "Добавить комментарий",
|
||||
"ErrorInvalidUserLastName": "Недопустимая фамилия",
|
||||
"ErrorInvalidUserFirstName": "Недопустимое имя"
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ class TextField extends React.Component {
|
||||
isRequired,
|
||||
hasError,
|
||||
labelText,
|
||||
errorMessage,
|
||||
|
||||
inputName,
|
||||
inputValue,
|
||||
@ -32,6 +33,7 @@ class TextField extends React.Component {
|
||||
<FieldContainer
|
||||
isRequired={isRequired}
|
||||
hasError={hasError}
|
||||
errorMessage={errorMessage}
|
||||
labelText={labelText}
|
||||
tooltipContent={tooltipContent}
|
||||
helpButtonHeaderContent={helpButtonHeaderContent}
|
||||
|
@ -242,8 +242,19 @@ class CreateUserForm extends React.Component {
|
||||
}
|
||||
|
||||
onInputChange = (event) => {
|
||||
const { userFormValidation } = this.props;
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile[event.target.name] = event.target.value;
|
||||
const value = event.target.value;
|
||||
const title = event.target.name;
|
||||
|
||||
if (!value.match(userFormValidation)) {
|
||||
stateCopy.errors[title] = true;
|
||||
} else {
|
||||
if (this.state.errors[title]) stateCopy.errors[title] = false;
|
||||
}
|
||||
|
||||
stateCopy.profile[title] = value;
|
||||
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
};
|
||||
@ -262,8 +273,20 @@ class CreateUserForm extends React.Component {
|
||||
this.setIsEdit();
|
||||
};
|
||||
|
||||
scrollToErrorForm = () => {
|
||||
const element = this.mainFieldsContainerRef.current;
|
||||
const parent = element.closest(".scroll-body");
|
||||
(parent || window).scrollTo(0, element.offsetTop);
|
||||
};
|
||||
|
||||
validate = () => {
|
||||
const { profile, errors: stateErrors } = this.state;
|
||||
|
||||
if (stateErrors.firstName || stateErrors.lastName) {
|
||||
this.scrollToErrorForm();
|
||||
return;
|
||||
}
|
||||
|
||||
const errors = {
|
||||
firstName: !profile.firstName.trim(),
|
||||
lastName: !profile.lastName.trim(),
|
||||
@ -274,9 +297,7 @@ class CreateUserForm extends React.Component {
|
||||
errors.firstName || errors.lastName || errors.email || errors.password;
|
||||
|
||||
if (hasError) {
|
||||
const element = this.mainFieldsContainerRef.current;
|
||||
const parent = element.closest(".scroll-body");
|
||||
(parent || window).scrollTo(0, element.offsetTop);
|
||||
this.scrollToErrorForm();
|
||||
}
|
||||
|
||||
this.setState({ errors: errors });
|
||||
@ -436,6 +457,9 @@ class CreateUserForm extends React.Component {
|
||||
const pattern = getUserContactsPattern();
|
||||
const contacts = getUserContacts(profile.contacts);
|
||||
|
||||
const notEmptyFirstName = Boolean(profile.firstName.trim());
|
||||
const notEmptyLastName = Boolean(profile.lastName.trim());
|
||||
|
||||
return (
|
||||
<>
|
||||
<MainContainer>
|
||||
@ -470,6 +494,9 @@ class CreateUserForm extends React.Component {
|
||||
<TextField
|
||||
isRequired={true}
|
||||
hasError={errors.firstName}
|
||||
{...(notEmptyFirstName && {
|
||||
errorMessage: t("ErrorInvalidUserFirstName"),
|
||||
})}
|
||||
labelText={`${t("FirstName")}:`}
|
||||
inputName="firstName"
|
||||
inputValue={profile.firstName}
|
||||
@ -481,6 +508,9 @@ class CreateUserForm extends React.Component {
|
||||
<TextField
|
||||
isRequired={true}
|
||||
hasError={errors.lastName}
|
||||
{...(notEmptyLastName && {
|
||||
errorMessage: t("ErrorInvalidUserLastName"),
|
||||
})}
|
||||
labelText={`${t("Common:LastName")}:`}
|
||||
inputName="lastName"
|
||||
inputValue={profile.lastName}
|
||||
@ -687,6 +717,7 @@ export default withRouter(
|
||||
setCroppedAvatar: peopleStore.avatarEditorStore.setCroppedAvatar,
|
||||
updateProfileInUsers: peopleStore.usersStore.updateProfileInUsers,
|
||||
updateCreatedAvatar: peopleStore.targetUserStore.updateCreatedAvatar,
|
||||
userFormValidation: auth.settingsStore.userFormValidation,
|
||||
}))(
|
||||
observer(
|
||||
withTranslation(["ProfileAction", "Common", "Translations"])(
|
||||
|
@ -238,8 +238,19 @@ class UpdateUserForm extends React.Component {
|
||||
}
|
||||
|
||||
onInputChange(event) {
|
||||
const { userFormValidation } = this.props;
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile[event.target.name] = event.target.value;
|
||||
const value = event.target.value;
|
||||
const title = event.target.name;
|
||||
|
||||
if (!value.match(userFormValidation)) {
|
||||
stateCopy.errors[title] = true;
|
||||
} else {
|
||||
if (this.state.errors[title]) stateCopy.errors[title] = false;
|
||||
}
|
||||
|
||||
stateCopy.profile[title] = value;
|
||||
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
}
|
||||
@ -278,21 +289,30 @@ class UpdateUserForm extends React.Component {
|
||||
this.setIsEdit();
|
||||
}
|
||||
|
||||
scrollToErrorForm = () => {
|
||||
const element = this.mainFieldsContainerRef.current;
|
||||
const parent = element.closest(".scroll-body");
|
||||
(parent || window).scrollTo(0, element.offsetTop);
|
||||
};
|
||||
validate() {
|
||||
const { profile } = this.state;
|
||||
const errors = {
|
||||
const { profile, errors } = this.state;
|
||||
|
||||
if (errors.firstName || errors.lastName) {
|
||||
this.scrollToErrorForm();
|
||||
return;
|
||||
}
|
||||
|
||||
const errorsObj = {
|
||||
firstName: !profile.firstName.trim(),
|
||||
lastName: !profile.lastName.trim(),
|
||||
};
|
||||
const hasError = errors.firstName || errors.lastName;
|
||||
const hasError = errorsObj.firstName || errorsObj.lastName;
|
||||
|
||||
if (hasError) {
|
||||
const element = this.mainFieldsContainerRef.current;
|
||||
const parent = element.closest(".scroll-body");
|
||||
(parent || window).scrollTo(0, element.offsetTop);
|
||||
this.scrollToErrorForm();
|
||||
}
|
||||
|
||||
this.setState({ errors: errors });
|
||||
this.setState({ errors: errorsObj });
|
||||
return !hasError;
|
||||
}
|
||||
|
||||
@ -615,6 +635,8 @@ class UpdateUserForm extends React.Component {
|
||||
|
||||
const pattern = getUserContactsPattern();
|
||||
const contacts = getUserContacts(profile.contacts);
|
||||
const notEmptyFirstName = Boolean(profile.firstName.trim());
|
||||
const notEmptyLastName = Boolean(profile.lastName.trim());
|
||||
//TODO: inject guestsCaption in 'ProfileTypePopupHelper' key instead of hardcoded 'Guests'
|
||||
const tooltipTypeContent = (
|
||||
<>
|
||||
@ -790,6 +812,9 @@ class UpdateUserForm extends React.Component {
|
||||
isRequired={true}
|
||||
hasError={errors.firstName}
|
||||
labelText={`${t("FirstName")}:`}
|
||||
{...(notEmptyFirstName && {
|
||||
errorMessage: t("ErrorInvalidUserFirstName"),
|
||||
})}
|
||||
inputName="firstName"
|
||||
inputValue={profile.firstName}
|
||||
inputIsDisabled={isLoading}
|
||||
@ -802,6 +827,9 @@ class UpdateUserForm extends React.Component {
|
||||
<TextField
|
||||
isRequired={true}
|
||||
hasError={errors.lastName}
|
||||
{...(notEmptyLastName && {
|
||||
errorMessage: t("ErrorInvalidUserLastName"),
|
||||
})}
|
||||
labelText={`${t("Common:LastName")}:`}
|
||||
inputName="lastName"
|
||||
inputValue={profile.lastName}
|
||||
@ -1020,6 +1048,7 @@ export default withRouter(
|
||||
isEditTargetUser: peopleStore.targetUserStore.isEditTargetUser,
|
||||
personal: auth.settingsStore.personal,
|
||||
setUserIsUpdate: auth.userStore.setUserIsUpdate,
|
||||
userFormValidation: auth.settingsStore.userFormValidation,
|
||||
}))(
|
||||
observer(
|
||||
withTranslation(["ProfileAction", "Common", "Translations"])(
|
||||
|
Loading…
Reference in New Issue
Block a user