Compare commits
10 Commits
master
...
feature/tf
Author | SHA1 | Date | |
---|---|---|---|
|
8433b6931a | ||
|
0f748501d4 | ||
|
d540f9dee5 | ||
|
0c0a4982fd | ||
|
4df919c899 | ||
|
f3db257ee2 | ||
|
a8780eee28 | ||
|
b565459077 | ||
|
219c9006da | ||
|
dbf06ffdc7 |
@ -11,6 +11,8 @@
|
||||
"EmailAndPasswordCopiedToClipboard": "Email and password copied to clipboard",
|
||||
"EnterAppCodeDescription": "Enter 6-digit generated code from your app. If you don't have access to your phone, use the backup codes.",
|
||||
"EnterAppCodeTitle": "Enter code from authentication app",
|
||||
"EnterSmsCodeDescription": "An SMS with portal access code has been sent to your <1>{{ currentNumber }}</1> mobile number. Please enter the code and click the «Continue» button. If no message is received for more than three minutes, click the «Send code again» link.",
|
||||
"EnterSmsCodeTitle": "Enter code from SMS",
|
||||
"EnterCodePlaceholder": "Enter code",
|
||||
"EnterPhone": "Enter mobile phone number",
|
||||
"GetCode": "Get code",
|
||||
@ -22,6 +24,7 @@
|
||||
"PortalDeactivateTitle": "Please confirm that you want to deactivate your DocSpace.",
|
||||
"PortalRemoveTitle": "Please confirm that you want to delete your DocSpace.",
|
||||
"Reactivate": "Reactivate",
|
||||
"SendCodeAgain": "Send code again",
|
||||
"SetAppButton": "Connect app",
|
||||
"SetAppDescription": "Two-factor authentication is enabled. Configure your authenticator app to continue working in the DocSpace. You can use Google Authenticator for <1>Android</1> and <4>iOS</4> or Authenticator for <8>Windows Phone</8>.",
|
||||
"SetAppInstallDescription": "To connect the app, scan the QR code or manually enter your secret key <1>{{ secretKey }}</1>, and then enter a 6-digit code from your app in the field below.",
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { useNavigate, useLocation } from "react-router-dom";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import Text from "@docspace/components/text";
|
||||
import TextInput from "@docspace/components/text-input";
|
||||
import InputPhone from "@docspace/components/input-phone";
|
||||
import Button from "@docspace/components/button";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { StyledPage, StyledBody, StyledContent } from "./StyledConfirm";
|
||||
@ -11,41 +11,44 @@ import FormWrapper from "@docspace/components/form-wrapper";
|
||||
import DocspaceLogo from "../../../DocspaceLogo";
|
||||
|
||||
const ChangePhoneForm = (props) => {
|
||||
const { t, greetingTitle } = props;
|
||||
const [currentNumber, setCurrentNumber] = useState("+00000000000");
|
||||
const { t, setMobilePhone } = props;
|
||||
const [currentNumber, setCurrentNumber] = useState("");
|
||||
const [phone, setPhone] = useState("");
|
||||
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
const onChange = (e) => {
|
||||
const value = e.target.value.replace(/[^0-9]/g, "");
|
||||
console.log(value);
|
||||
setPhone(value);
|
||||
};
|
||||
|
||||
const onSubmit = async () => {
|
||||
const res = await setMobilePhone(phone);
|
||||
console.log(res);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledPage>
|
||||
<StyledContent>
|
||||
<StyledBody>
|
||||
<DocspaceLogo className="docspace-logo" />
|
||||
<Text fontSize="23px" fontWeight="700" className="title">
|
||||
{greetingTitle}
|
||||
</Text>
|
||||
|
||||
<FormWrapper>
|
||||
<div className="subtitle">
|
||||
<Text fontSize="16px" fontWeight="600" className="phone-title">
|
||||
{t("EnterPhone")}
|
||||
</Text>
|
||||
<Text>
|
||||
{t("CurrentNumber")}: {currentNumber}
|
||||
</Text>
|
||||
{currentNumber && (
|
||||
<Text>
|
||||
{t("CurrentNumber")}: {currentNumber}
|
||||
</Text>
|
||||
)}
|
||||
<Text>{t("PhoneSubtitle")}</Text>
|
||||
</div>
|
||||
|
||||
<TextInput
|
||||
className="phone-input"
|
||||
id="phone"
|
||||
name="phone"
|
||||
type="phone"
|
||||
size="large"
|
||||
scale={true}
|
||||
isAutoFocussed={true}
|
||||
tabIndex={1}
|
||||
hasError={false}
|
||||
guide={false}
|
||||
/>
|
||||
<InputPhone className="phone-input" scaled onChange={onChange} />
|
||||
|
||||
<Button
|
||||
primary
|
||||
@ -54,6 +57,7 @@ const ChangePhoneForm = (props) => {
|
||||
label={t("GetCode")}
|
||||
tabIndex={2}
|
||||
isDisabled={false}
|
||||
onClick={onSubmit}
|
||||
/>
|
||||
</FormWrapper>
|
||||
</StyledBody>
|
||||
@ -62,6 +66,10 @@ const ChangePhoneForm = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ auth }) => ({
|
||||
greetingTitle: auth.settingsStore.greetingSettings,
|
||||
}))(withTranslation("Confirm")(withLoader(observer(ChangePhoneForm))));
|
||||
export default inject(({ auth }) => {
|
||||
const { tfaStore } = auth;
|
||||
const { setMobilePhone } = tfaStore;
|
||||
return {
|
||||
setMobilePhone,
|
||||
};
|
||||
})(withTranslation("Confirm")(withLoader(observer(ChangePhoneForm))));
|
||||
|
@ -0,0 +1,64 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { withTranslation } from "react-i18next";
|
||||
import Text from "@docspace/components/text";
|
||||
import TextInput from "@docspace/components/text-input";
|
||||
import Button from "@docspace/components/button";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { StyledPage, StyledBody, StyledContent } from "./StyledConfirm";
|
||||
import withLoader from "../withLoader";
|
||||
import FormWrapper from "@docspace/components/form-wrapper";
|
||||
import DocspaceLogo from "../../../DocspaceLogo";
|
||||
|
||||
const PhoneAuth = (props) => {
|
||||
const { t } = props;
|
||||
const [currentNumber, setCurrentNumber] = useState("");
|
||||
|
||||
return (
|
||||
<StyledPage>
|
||||
<StyledContent>
|
||||
<StyledBody>
|
||||
<DocspaceLogo className="docspace-logo" />
|
||||
|
||||
<FormWrapper>
|
||||
<div className="subtitle">
|
||||
<Text fontSize="16px" fontWeight="600" className="phone-title">
|
||||
{t("EnterSmsCodeTitle")}
|
||||
</Text>
|
||||
|
||||
<Text>
|
||||
<Trans
|
||||
t={t}
|
||||
i18nKey="EnterSmsCodeDescription"
|
||||
ns="Confirm"
|
||||
key={currentNumber}
|
||||
>
|
||||
An SMS with portal access code has been sent to your
|
||||
<strong>{{ currentNumber }}</strong> mobile number. Please
|
||||
enter the code and click the «Continue» button. If no message
|
||||
is received for more than three minutes, click the «Send code
|
||||
again» link.
|
||||
</Trans>
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<TextInput className="phone-input" scaled />
|
||||
|
||||
<Button
|
||||
primary
|
||||
scale
|
||||
size="medium"
|
||||
label={t("Common:ContinueButton")}
|
||||
tabIndex={2}
|
||||
isDisabled={false}
|
||||
/>
|
||||
</FormWrapper>
|
||||
</StyledBody>
|
||||
</StyledContent>
|
||||
</StyledPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ auth }) => ({
|
||||
greetingTitle: auth.settingsStore.greetingSettings,
|
||||
}))(withTranslation(["Confirm", "Common"])(withLoader(observer(PhoneAuth))));
|
@ -164,9 +164,7 @@ class ThirdPartyServices extends React.Component {
|
||||
(consumer) =>
|
||||
consumer.title !== "Bitly" &&
|
||||
consumer.title !== "WordPress" &&
|
||||
consumer.title !== "DocuSign" &&
|
||||
consumer.name !== "clickatell" && //TODO: hide while 2fa by sms is not working
|
||||
consumer.name !== "twilio"
|
||||
consumer.title !== "DocuSign"
|
||||
);
|
||||
|
||||
const imgSrc = theme.isBase ? IntegrationSvgUrl : IntegrationDarkSvgUrl;
|
||||
|
@ -163,13 +163,12 @@ const TwoFactorAuth = (props) => {
|
||||
label: t("Disabled"),
|
||||
value: "none",
|
||||
},
|
||||
//TODO: hide while 2fa by sms is not working
|
||||
/*{
|
||||
{
|
||||
id: "by-sms",
|
||||
label: t("BySms"),
|
||||
value: "sms",
|
||||
disabled: !smsDisabled,
|
||||
},*/
|
||||
},
|
||||
{
|
||||
id: "by-app",
|
||||
label: t("ByApp"),
|
||||
|
@ -298,3 +298,17 @@ export function getPortal() {
|
||||
};
|
||||
return request(options);
|
||||
}
|
||||
|
||||
export function setMobilePhone(mobilePhone) {
|
||||
const data = {
|
||||
mobilePhone,
|
||||
};
|
||||
|
||||
const options = {
|
||||
method: "post",
|
||||
url: "/authentication/setphone",
|
||||
data,
|
||||
};
|
||||
|
||||
return request(options);
|
||||
}
|
||||
|
@ -69,6 +69,10 @@ class TfaStore {
|
||||
unlinkApp = async (id) => {
|
||||
return api.settings.unlinkTfaApp(id);
|
||||
};
|
||||
|
||||
setMobilePhone = async (mobilePhone) => {
|
||||
return await api.portal.setMobilePhone(mobilePhone);
|
||||
};
|
||||
}
|
||||
|
||||
export default TfaStore;
|
||||
|
@ -9,10 +9,10 @@ export async function login(
|
||||
try {
|
||||
const response = await api.user.login(user, hash, session, captchaToken);
|
||||
|
||||
if (!response || (!response.token && !response.tfa))
|
||||
if (!response || (!response.token && !response.tfa && !response.sms))
|
||||
throw response.error.message;
|
||||
|
||||
if (response.tfa && response.confirmUrl) {
|
||||
if ((response.tfa || response.sms) && response.confirmUrl) {
|
||||
const url = response.confirmUrl.replace(window.location.origin, "");
|
||||
return url;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ const InputPhone = ({
|
||||
searchPlaceholderText,
|
||||
searchEmptyMessage,
|
||||
errorMessage,
|
||||
className,
|
||||
} = props) => {
|
||||
const [country, setCountry] = useState(defaultCountry);
|
||||
const [phoneValue, setPhoneValue] = useState(country.dialCode);
|
||||
@ -140,6 +141,7 @@ const InputPhone = ({
|
||||
|
||||
return (
|
||||
<StyledBox
|
||||
className={className}
|
||||
hasError={!isValid}
|
||||
displayProp="flex"
|
||||
alignItems="center"
|
||||
@ -224,6 +226,8 @@ const InputPhone = ({
|
||||
};
|
||||
|
||||
InputPhone.propTypes = {
|
||||
/** Accepts class */
|
||||
className: PropTypes.string,
|
||||
/** Default selected country */
|
||||
defaultCountry: PropTypes.object.isRequired,
|
||||
/** Text displayed on the Input placeholder */
|
||||
|
Loading…
Reference in New Issue
Block a user