Fix bug 68984 - Client: fix LDAP empty fields validation

This commit is contained in:
Dmitry Sychugov 2024-07-18 18:57:21 +05:00
parent 0476abe5ba
commit e1c2d72948
8 changed files with 209 additions and 116 deletions

View File

@ -91,9 +91,6 @@ const StyledLdapPage = styled(Box)`
.ldap_attribute-mapping {
margin-top: 16px;
margin-bottom: 12px;
input {
margin-bottom: 16px;
}
display: grid;
grid-gap: 12px;
}

View File

@ -38,10 +38,11 @@ import { FieldContainer } from "@docspace/shared/components/field-container";
import { PRODUCT_NAME } from "@docspace/shared/constants";
import AccessSelector from "SRC_DIR/components/AccessSelector";
import { isMobile } from "@docspace/shared/utils";
import LdapFieldComponent from "./LdapFieldComponent";
const FIRST_NAME = "firstName",
SECOND_NAME = "secondName",
MAIL = "mailName",
MAIL = "mail",
AVATAR = "avatarAttribute",
QUOTA = "userQuotaLimit";
@ -108,108 +109,105 @@ const AttributeMapping = (props) => {
<HelpButton tooltipContent={t("LdapAdvancedSettingsTooltip")} />
</div>
<Box className="ldap_attribute-mapping">
<div>
<FieldContainer
style={FIELD_STYLE}
isVertical
labelVisible={true}
errorMessage={t("Common:EmptyFieldError")}
<FieldContainer
style={FIELD_STYLE}
isVertical
labelVisible={true}
errorMessage={t("Common:EmptyFieldError")}
hasError={errors.firstName}
labelText={t("LdapFirstName")}
isRequired
>
<LdapFieldComponent
name={FIRST_NAME}
hasError={errors.firstName}
labelText={t("LdapFirstName")}
isRequired
>
<TextInput
name={FIRST_NAME}
hasError={errors.firstName}
onChange={onChangeValue}
value={firstName}
scale
isDisabled={!isLdapEnabled || isUIDisabled}
tabIndex={7}
/>
</FieldContainer>
onChange={onChangeValue}
value={firstName}
scale
isDisabled={!isLdapEnabled || isUIDisabled}
tabIndex={7}
/>
</FieldContainer>
<FieldContainer
style={FIELD_STYLE}
isVertical
labelVisible={true}
errorMessage={t("Common:EmptyFieldError")}
<FieldContainer
style={FIELD_STYLE}
isVertical
labelVisible={true}
errorMessage={t("Common:EmptyFieldError")}
hasError={errors.mail}
labelText={t("LdapMail")}
isRequired
>
<LdapFieldComponent
name={MAIL}
hasError={errors.mail}
labelText={t("LdapMail")}
isRequired
>
<TextInput
name={MAIL}
hasError={errors.mail}
onChange={onChangeValue}
value={mail}
scale
isDisabled={!isLdapEnabled || isUIDisabled}
tabIndex={9}
/>
</FieldContainer>
onChange={onChangeValue}
value={mail}
scale
isDisabled={!isLdapEnabled || isUIDisabled}
tabIndex={9}
/>
</FieldContainer>
<FieldContainer
style={FIELD_STYLE}
isVertical
labelVisible={true}
<FieldContainer
style={FIELD_STYLE}
isVertical
labelVisible={true}
hasError={errors.userQuotaLimit}
labelText={t("LdapQuota")}
tooltipContent={t("LdapUserQuotaTooltip")}
inlineHelpButton
>
<TextInput
name={QUOTA}
hasError={errors.userQuotaLimit}
labelText={t("LdapQuota")}
tooltipContent={t("LdapUserQuotaTooltip")}
inlineHelpButton
>
<TextInput
name={QUOTA}
hasError={errors.userQuotaLimit}
onChange={onChangeValue}
value={userQuotaLimit}
scale
isDisabled={!isLdapEnabled || isUIDisabled}
tabIndex={11}
/>
</FieldContainer>
</div>
<div>
<FieldContainer
style={FIELD_STYLE}
isVertical
labelVisible={true}
errorMessage={t("Common:EmptyFieldError")}
hasError={errors.secondName}
labelText={t("LdapSecondName")}
isRequired
>
<TextInput
name={SECOND_NAME}
hasError={errors.secondName}
onChange={onChangeValue}
value={secondName}
scale
isDisabled={!isLdapEnabled || isUIDisabled}
tabIndex={8}
/>
</FieldContainer>
onChange={onChangeValue}
value={userQuotaLimit}
scale
isDisabled={!isLdapEnabled || isUIDisabled}
tabIndex={11}
/>
</FieldContainer>
<FieldContainer
style={FIELD_STYLE}
isVertical
labelVisible={true}
<FieldContainer
style={FIELD_STYLE}
isVertical
labelVisible={true}
errorMessage={t("Common:EmptyFieldError")}
hasError={errors.secondName}
labelText={t("LdapSecondName")}
isRequired
>
<LdapFieldComponent
name={SECOND_NAME}
hasError={errors.secondName}
onChange={onChangeValue}
value={secondName}
scale
isDisabled={!isLdapEnabled || isUIDisabled}
tabIndex={8}
/>
</FieldContainer>
<FieldContainer
style={FIELD_STYLE}
isVertical
labelVisible={true}
hasError={errors.avatarAttribute}
labelText={t("LdapAvatar")}
>
<TextInput
name={AVATAR}
hasError={errors.avatarAttribute}
labelText={t("LdapAvatar")}
>
<TextInput
name={AVATAR}
hasError={errors.avatarAttribute}
onChange={onChangeValue}
value={avatarAttribute}
scale
isDisabled={!isLdapEnabled || isUIDisabled}
tabIndex={10}
/>
</FieldContainer>
</div>
onChange={onChangeValue}
value={avatarAttribute}
scale
isDisabled={!isLdapEnabled || isUIDisabled}
tabIndex={10}
/>
</FieldContainer>
</Box>
<Box marginProp="0 0 24px 0">
<Box marginProp="24px 0 24px 0">
<Box
displayProp="flex"
flexDirection="column"

View File

@ -29,9 +29,9 @@ import { useTranslation } from "react-i18next";
import { Box } from "@docspace/shared/components/box";
import { HelpButton } from "@docspace/shared/components/help-button";
import { TextInput } from "@docspace/shared/components/text-input";
import { FieldContainer } from "@docspace/shared/components/field-container";
import { ToggleButton } from "@docspace/shared/components/toggle-button";
import LdapFieldComponent from "./LdapFieldComponent";
const LOGIN = "login",
PASSWORD = "password";
@ -87,7 +87,7 @@ const AuthenticationContainer = ({
inlineHelpButton
isRequired
>
<TextInput
<LdapFieldComponent
name={LOGIN}
hasError={errors.login}
onChange={onChangeValue}
@ -108,7 +108,7 @@ const AuthenticationContainer = ({
inlineHelpButton
isRequired
>
<TextInput
<LdapFieldComponent
name={PASSWORD}
type="password"
hasError={errors.password}

View File

@ -28,9 +28,8 @@ import { inject, observer } from "mobx-react";
import { useTranslation } from "react-i18next";
import { Box } from "@docspace/shared/components/box";
import { TextInput } from "@docspace/shared/components/text-input";
import { FieldContainer } from "@docspace/shared/components/field-container";
import { Textarea } from "@docspace/shared/components/textarea";
import LdapFieldComponent from "./LdapFieldComponent";
const USER_DN = "userDN",
SERVER = "server",
@ -97,7 +96,7 @@ const ConnectionSettings = (props) => {
inlineHelpButton
isRequired
>
<TextInput
<LdapFieldComponent
name={SERVER}
hasError={errors.server}
onChange={onChangeValue}
@ -118,7 +117,7 @@ const ConnectionSettings = (props) => {
inlineHelpButton
isRequired
>
<TextInput
<LdapFieldComponent
name={USER_DN}
hasError={errors.userDN}
onChange={onChangeValue}
@ -139,7 +138,7 @@ const ConnectionSettings = (props) => {
inlineHelpButton
isRequired
>
<TextInput
<LdapFieldComponent
name={LOGIN_ATTRIBUTE}
hasError={errors.loginAttribute}
onChange={onChangeValue}
@ -162,7 +161,7 @@ const ConnectionSettings = (props) => {
inlineHelpButton
isRequired
>
<TextInput
<LdapFieldComponent
pattern="[0-9]*"
name={PORT_NUMBER}
hasError={errors.portNumber}
@ -185,7 +184,8 @@ const ConnectionSettings = (props) => {
inlineHelpButton
isRequired
>
<Textarea
<LdapFieldComponent
isTextArea
name={USER_FILTER}
hasError={errors.userFilter}
onChange={onChangeValue}

View File

@ -30,10 +30,9 @@ import { useTranslation } from "react-i18next";
import { ToggleButton } from "@docspace/shared/components/toggle-button";
import { HelpButton } from "@docspace/shared/components/help-button";
import { Box } from "@docspace/shared/components/box";
import { TextInput } from "@docspace/shared/components/text-input";
import { FieldContainer } from "@docspace/shared/components/field-container";
import { Textarea } from "@docspace/shared/components/textarea";
import { PRODUCT_NAME } from "@docspace/shared/constants";
import LdapFieldComponent from "./LdapFieldComponent";
const FIELD_STYLE = { marginBottom: "0px" };
@ -114,7 +113,7 @@ const GroupMembership = (props) => {
hasError={errors.groupDN}
tooltipContent={t("LdapGroupDNTooltip")}
>
<TextInput
<LdapFieldComponent
className="field-input"
onChange={onChange}
name={GROUP_DN}
@ -135,7 +134,7 @@ const GroupMembership = (props) => {
isRequired
tooltipContent={t("LdapGroupUserAttributeTooltip")}
>
<TextInput
<LdapFieldComponent
className="field-input"
onChange={onChange}
name={USER_ATTRIBUTE}
@ -158,7 +157,8 @@ const GroupMembership = (props) => {
inlineHelpButton
isRequired
>
<Textarea
<LdapFieldComponent
isTextArea
value={groupFilter}
onChange={onChange}
hasError={errors.groupFilter}
@ -178,7 +178,7 @@ const GroupMembership = (props) => {
isRequired
tooltipContent={t("LdapGroupNameAttributeTooltip")}
>
<TextInput
<LdapFieldComponent
className="field-input"
onChange={onChange}
name={GROUP_NAME_ATTRIBUTE}
@ -198,7 +198,7 @@ const GroupMembership = (props) => {
isRequired
tooltipContent={t("LdapGroupAttributeTooltip")}
>
<TextInput
<LdapFieldComponent
className="field-input"
onChange={onChange}
name={GROUP_ATTRIBUTE}

View File

@ -0,0 +1,90 @@
// (c) Copyright Ascensio System SIA 2009-2024
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
// any third-party rights.
//
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
import React from "react";
import { inject, observer } from "mobx-react";
import { TextInput } from "@docspace/shared/components/text-input";
import { Textarea } from "@docspace/shared/components/textarea";
const LdapFieldComponent = (props) => {
const {
isTextArea,
errors,
removeErrorField,
setErrorField,
name,
onChange,
...prop
} = props;
const onChangeFn = (e) => {
const { value, name } = e.target;
if (value.trim() !== "") {
removeErrorField(name);
} else {
setErrorField(name);
}
onChange && onChange(e);
};
const onFocus = (e) => {
const name = e.target.name;
if (errors[name]) {
removeErrorField(name);
}
};
const onBlur = (e) => {
if (e.target.value.trim() === "") {
setErrorField(e.target.name);
}
};
if (isTextArea)
return <Textarea name={name} onChange={onChangeFn} {...prop} />;
return (
<TextInput
name={name}
onBlur={onBlur}
onFocus={onFocus}
onChange={onChangeFn}
{...prop}
/>
);
};
export default inject(({ ldapStore }) => {
const { errors, removeErrorField, setErrorField } = ldapStore;
return {
errors,
removeErrorField,
setErrorField,
};
})(observer(LdapFieldComponent));

View File

@ -232,6 +232,14 @@ class LdapFormStore {
this.requiredSettings.userDN = userDN;
};
removeErrorField = (fieldName) => {
delete this.errors[fieldName];
};
setErrorField = (fieldName) => {
this.errors[fieldName] = true;
};
setLoginAttribute = (loginAttribute) => {
this.requiredSettings.loginAttribute = loginAttribute;
};

View File

@ -146,7 +146,7 @@ const Textarea = ({
className={className}
style={style}
isDisabled={isDisabled}
hasError={isError}
hasError={isError || hasError}
heightScale={heightScale}
heightTextAreaProp={stringifiedHeight}
isFullHeight={isFullHeight}