Web: Login: Added error handler.
This commit is contained in:
parent
a85a721a3b
commit
c4d2048e3a
@ -53,6 +53,8 @@ const {
|
||||
strongBlue,
|
||||
lightGrayishStrongBlue,
|
||||
darkRed,
|
||||
|
||||
lightErrorStatus,
|
||||
} = globalColors;
|
||||
|
||||
const Base = {
|
||||
@ -2785,6 +2787,11 @@ const Base = {
|
||||
container: {
|
||||
backgroundColor: grayLightMid,
|
||||
},
|
||||
|
||||
captcha: {
|
||||
border: `1px solid ${lightErrorStatus}`,
|
||||
color: lightErrorStatus,
|
||||
},
|
||||
},
|
||||
|
||||
facebookButton: {
|
||||
|
@ -47,6 +47,8 @@ const {
|
||||
strongBlue,
|
||||
lightGrayishStrongBlue,
|
||||
darkRed,
|
||||
|
||||
darkErrorStatus,
|
||||
} = globalColors;
|
||||
|
||||
const Dark = {
|
||||
@ -2791,6 +2793,11 @@ const Dark = {
|
||||
container: {
|
||||
backgroundColor: "#474747",
|
||||
},
|
||||
|
||||
captcha: {
|
||||
border: `1px solid ${darkErrorStatus}`,
|
||||
color: darkErrorStatus,
|
||||
},
|
||||
},
|
||||
|
||||
facebookButton: {
|
||||
|
@ -56,6 +56,9 @@ const globalColors = {
|
||||
hoverError: "#F7CDBE",
|
||||
hoverInfo: "#F8F7BF",
|
||||
hoverWarning: "#F7E6BE",
|
||||
|
||||
lightErrorStatus: "#F24724",
|
||||
darkErrorStatus: "#E06451",
|
||||
};
|
||||
|
||||
export default globalColors;
|
||||
|
@ -7,6 +7,7 @@
|
||||
"InvalidUsernameOrPassword": "Invalid username or password",
|
||||
"LoginWithAccountNotFound": "Can't find associated third-party account. You need to connect your social networking account at the profile editing page first.",
|
||||
"LoginWithBruteForce": "Authorization temporarily blocked",
|
||||
"LoginWithBruteForceCaptcha": "Confirm that you are not a robot",
|
||||
"RecaptchaInvalid": "Invalid Recaptcha",
|
||||
"SsoAttributesNotFound": "Authentication failed (assertion attributes not found)",
|
||||
"SsoAuthFailed": "Authentication failed",
|
||||
|
@ -22,6 +22,11 @@ interface ILoginContentProps {
|
||||
enabledJoin?: boolean;
|
||||
}
|
||||
|
||||
interface IStyledCaptchaProps {
|
||||
isCaptchaError?: boolean;
|
||||
theme?: IUserTheme;
|
||||
}
|
||||
|
||||
export const LoginFormWrapper = styled.div`
|
||||
display: grid;
|
||||
grid-template-rows: ${(props: ILoginFormWrapperProps) =>
|
||||
@ -38,7 +43,7 @@ export const LoginFormWrapper = styled.div`
|
||||
}
|
||||
|
||||
.bg-cover {
|
||||
background-image: ${props => props.bgPattern};
|
||||
background-image: ${(props) => props.bgPattern};
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-size: cover;
|
||||
@ -52,27 +57,46 @@ export const LoginFormWrapper = styled.div`
|
||||
background-image: none;
|
||||
}
|
||||
}
|
||||
|
||||
.captcha-container {
|
||||
margin: 24px 0;
|
||||
}
|
||||
`;
|
||||
|
||||
export const LoginContent = styled.div`
|
||||
min-height: ${(props: ILoginContentProps) => props.enabledJoin ? "calc(100vh - 68px)" : "100vh"};
|
||||
flex: 1 0 auto;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
|
||||
@media ${hugeMobile} {
|
||||
min-height: 100%;
|
||||
justify-content: start;
|
||||
}
|
||||
min-height: ${(props: ILoginContentProps) =>
|
||||
props.enabledJoin ? "calc(100vh - 68px)" : "100vh"};
|
||||
flex: 1 0 auto;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
|
||||
@media ${hugeMobile} {
|
||||
min-height: 100%;
|
||||
justify-content: start;
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledCaptcha = styled.div`
|
||||
margin: 24px 0;
|
||||
|
||||
width: fit-content;
|
||||
.captcha-wrapper {
|
||||
${(props: IStyledCaptchaProps) =>
|
||||
props.isCaptchaError &&
|
||||
css`
|
||||
border: ${props.theme.login.captcha.border};
|
||||
padding: 4px 4px 4px 2px;
|
||||
`};
|
||||
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
${(props: IStyledCaptchaProps) =>
|
||||
props.isCaptchaError &&
|
||||
css`
|
||||
p {
|
||||
color: ${props.theme.login.captcha.color};
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
@ -17,6 +17,7 @@ import { thirdPartyLogin } from "@docspace/common/api/user";
|
||||
import { setWithCredentialsStatus } from "@docspace/common/api/client";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
import ReCAPTCHA from "react-google-recaptcha";
|
||||
import { StyledCaptcha } from "../StyledLogin";
|
||||
|
||||
interface ILoginFormProps {
|
||||
isLoading: boolean;
|
||||
@ -64,6 +65,9 @@ const LoginForm: React.FC<ILoginFormProps> = ({
|
||||
const [isWithoutPasswordLogin, setIsWithoutPasswordLogin] =
|
||||
useState(IS_ROOMS_MODE);
|
||||
|
||||
const [isCaptchaSuccessful, setIsCaptchaSuccess] = useState(false);
|
||||
const [isCaptchaError, setIsCaptchaError] = useState(false);
|
||||
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const { t, ready } = useTranslation(["Login", "Common"]);
|
||||
@ -152,6 +156,11 @@ const LoginForm: React.FC<ILoginFormProps> = ({
|
||||
let captchaToken = "";
|
||||
|
||||
if (recaptchaPublicKey && isCaptcha) {
|
||||
if (!isCaptchaSuccessful) {
|
||||
setIsCaptchaError(true);
|
||||
return;
|
||||
}
|
||||
|
||||
captchaToken = captchaRef.current.getValue();
|
||||
}
|
||||
|
||||
@ -277,6 +286,10 @@ const LoginForm: React.FC<ILoginFormProps> = ({
|
||||
setIsLoading(false);
|
||||
};
|
||||
|
||||
const onSuccessfullyComplete = () => {
|
||||
setIsCaptchaSuccess(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<form className="auth-form-container">
|
||||
<FieldContainer
|
||||
@ -383,13 +396,19 @@ const LoginForm: React.FC<ILoginFormProps> = ({
|
||||
/>
|
||||
)}
|
||||
{recaptchaPublicKey && isCaptcha && (
|
||||
<div className="captcha-container">
|
||||
<ReCAPTCHA
|
||||
sitekey={recaptchaPublicKey}
|
||||
ref={captchaRef}
|
||||
theme={isBaseTheme ? "light" : "dark"}
|
||||
/>
|
||||
</div>
|
||||
<StyledCaptcha isCaptchaError={isCaptchaError}>
|
||||
<div className="captcha-wrapper">
|
||||
<ReCAPTCHA
|
||||
sitekey={recaptchaPublicKey}
|
||||
ref={captchaRef}
|
||||
theme={isBaseTheme ? "light" : "dark"}
|
||||
onChange={onSuccessfullyComplete}
|
||||
/>
|
||||
</div>
|
||||
{isCaptchaError && (
|
||||
<Text>{t("Errors:LoginWithBruteForceCaptcha")}</Text>
|
||||
)}
|
||||
</StyledCaptcha>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
Loading…
Reference in New Issue
Block a user