Client:Pages:Confirm: remove old confirm pages

This commit is contained in:
Darya Umrikhina 2024-08-09 18:24:32 +04:00
parent 3ff39739b7
commit 9159fd3801
21 changed files with 0 additions and 3917 deletions

View File

@ -1,96 +0,0 @@
// (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 styled, { css } from "styled-components";
import { isIOS, isFirefox, isMobileOnly } from "react-device-detect";
import { inject, observer } from "mobx-react";
import { getBgPattern } from "@docspace/shared/utils/common";
import { mobile } from "@docspace/shared/utils";
import { Scrollbar } from "@docspace/shared/components/scrollbar";
const StyledWrapper = styled.div`
height: ${(props) =>
props.height
? props.height
: isIOS && !isFirefox
? "calc(var(--vh, 1vh) * 100)"
: "100vh"};
width: 100vw;
z-index: 0;
display: flex;
flex-direction: row;
box-sizing: border-box;
@media ${mobile} {
height: auto;
min-height: 100%;
width: 100%;
min-width: 100%;
}
`;
const BgBlock = styled.div`
background-image: ${(props) => props.bgPattern};
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
position: fixed;
top: 0;
right: 0;
left: 0;
bottom: 0;
z-index: -1;
@media ${mobile} {
background-image: none;
}
`;
const ConfirmWrapper = (props) => {
const { children, currentColorScheme, height } = props;
const bgPattern = getBgPattern(currentColorScheme?.id);
const content = (
<>
<BgBlock bgPattern={bgPattern} />
{children}
</>
);
return (
<StyledWrapper height={height}>
{!!height ? content : <Scrollbar>{content}</Scrollbar>}
</StyledWrapper>
);
};
export default inject(({ settingsStore }) => {
const { currentColorScheme } = settingsStore;
return {
currentColorScheme,
};
})(observer(ConfirmWrapper));

View File

@ -1,39 +0,0 @@
// (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 { Outlet } from "react-router-dom";
import ErrorBoundaryWrapper from "SRC_DIR/components/ErrorBoundaryWrapper";
export const Component = () => {
//console.log("Confirm render");
return (
<ErrorBoundaryWrapper>
<Outlet />
</ErrorBoundaryWrapper>
);
};

View File

@ -1,83 +0,0 @@
// (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 { useTranslation, Trans } from "react-i18next";
import { ColorTheme, ThemeId } from "@docspace/shared/components/color-theme";
import { IconButton } from "@docspace/shared/components/icon-button";
import { Text } from "@docspace/shared/components/text";
import ArrowIcon from "PUBLIC_DIR/images/arrow.left.react.svg?url";
import { PRODUCT_NAME } from "@docspace/shared/constants";
const DEFAULT_CREATION_TEXT =
"A {{productName}} account will be created for {{email}}. Please, complete your registration:";
const GreetingUserContainer = ({
email,
onClickBack,
emailFromLink,
type,
defaultText,
}) => {
const { t } = useTranslation(["Confirm", "Common"]);
return (
<div className="greeting-container">
<div className="back-sign-in-container">
{type === "LinkInvite" && !emailFromLink && (
<div className="back-button">
<IconButton size={16} iconName={ArrowIcon} onClick={onClickBack} />
<Text fontWeight={600} onClick={onClickBack}>
{t("Common:Back")}
</Text>
</div>
)}
<Text fontWeight={600} fontSize={"16px"}>
{t("SignUp")}
</Text>
</div>
<Text>
<Trans
t={t}
i18nKey="AccountWillBeCreated"
ns="Confirm"
defaults={DEFAULT_CREATION_TEXT}
values={{
email,
}}
portalName={PRODUCT_NAME}
components={{
1: <ColorTheme tag="a" themeId={ThemeId.Link} isHovered={false} />,
}}
/>
</Text>
</div>
);
};
export default GreetingUserContainer;

View File

@ -1,69 +0,0 @@
// (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 { inject, observer } from "mobx-react";
import { setLanguageForUnauthorized } from "@docspace/shared/utils/common";
import { LanguageCombobox } from "@docspace/shared/components/language-combobox";
import { TPortalCultures } from "@docspace/shared/api/settings/types";
import { DeviceType } from "@docspace/shared/enums";
export interface TLanguageCombobox {
cultures: TPortalCultures;
currentDeviceType: string;
currentCultureName: string;
}
const LanguageComboboxWrapper = (props: TLanguageCombobox) => {
const { cultures, currentCultureName, currentDeviceType } = props;
const onLanguageSelect = (culture: { key: string }) => {
const { key } = culture;
setLanguageForUnauthorized(key);
};
const isMobileView = currentDeviceType === DeviceType.mobile;
if (isMobileView) return <></>;
return (
<LanguageCombobox
className="language-combo-box"
onSelectLanguage={onLanguageSelect}
cultures={cultures}
selectedCulture={currentCultureName}
withBorder={!isMobileView}
/>
);
};
export default inject<TStore>(({ settingsStore }) => {
const { currentDeviceType } = settingsStore;
return {
currentDeviceType,
};
})(observer(LanguageComboboxWrapper));

View File

@ -1,170 +0,0 @@
// (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 styled from "styled-components";
import {
mobile,
tablet,
getCorrectFourValuesStyle,
} from "@docspace/shared/utils";
export const StyledPage = styled.div`
display: flex;
flex-direction: column;
align-items: center;
margin: 0 auto;
max-width: 960px;
box-sizing: border-box;
@media ${tablet} {
padding: 0 16px;
}
@media ${mobile} {
width: 100%;
padding: ${({ theme }) =>
getCorrectFourValuesStyle("32px 8px 0 16px", theme.interfaceDirection)};
.language-combo-box {
display: none;
}
}
.subtitle {
margin-bottom: 32px;
}
.password-form {
width: 100%;
margin-bottom: 8px;
}
.subtitle {
margin-bottom: 32px;
}
.language-combo-box {
position: absolute;
right: 28px;
top: 28px;
}
`;
export const StyledContent = styled.div`
min-height: 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 ${mobile} {
width: 100%;
justify-content: start;
min-height: 100%;
}
`;
export const StyledHeader = styled.div`
.title {
margin-bottom: 32px;
text-align: center;
}
.subtitle {
margin-bottom: 32px;
}
.portal-logo {
display: flex;
align-items: center;
justify-content: center;
padding-bottom: 40px;
}
@media ${mobile} {
margin-top: 0;
}
`;
export const StyledBody = styled.div`
display: flex;
flex-direction: column;
align-items: center;
margin: 56px auto;
@media ${mobile} {
width: 100%;
margin: 0 auto;
}
.title {
margin-bottom: 32px;
text-align: center;
}
.subtitle {
margin-bottom: 32px;
}
.portal-logo {
display: flex;
align-items: center;
justify-content: center;
padding-bottom: 40px;
}
.password-field-wrapper {
width: 100%;
}
.password-change-form {
margin-top: 32px;
margin-bottom: 16px;
}
.phone-input {
margin-bottom: 24px;
}
.delete-profile-confirm {
margin-bottom: 8px;
}
.phone-title {
margin-bottom: 8px;
}
`;
export const ButtonsWrapper = styled.div`
display: flex;
flex-direction: row;
gap: 16px;
width: 100%;
`;

View File

@ -1,177 +0,0 @@
// (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 styled, { css } from "styled-components";
import { Box } from "@docspace/shared/components/box";
import { mobile, tablet } from "@docspace/shared/utils";
const DESKTOP_WIDTH = 384;
const TABLET_WIDTH = 480;
export const StyledCreateUserContent = styled.div`
margin: 88px auto;
@media ${mobile} {
margin-top: 0px;
}
`;
export const GreetingContainer = styled.div`
display: flex;
flex-direction: column;
align-items: left;
height: 100%;
width: ${DESKTOP_WIDTH}px;
margin-bottom: 32px;
@media ${tablet} {
width: 100%;
max-width: ${TABLET_WIDTH}px;
}
.tooltip {
p {
text-align: center;
}
@media ${mobile} {
padding: 0 25px;
}
}
.portal-logo {
width: 100%;
padding-bottom: 16px;
height: 26.56px;
display: flex;
align-items: center;
justify-content: center;
.injected-svg {
height: 26.56px;
}
}
`;
export const RegisterContainer = styled.div`
height: 100%;
width: 100%;
.or-label {
color: ${(props) => props.theme.invitePage.textColor};
margin: 0 8px;
}
.line {
display: flex;
width: 100%;
align-items: center;
color: ${(props) => props.theme.invitePage.borderColor};
padding-top: 35px;
margin-bottom: 32px;
}
.line:before,
.line:after {
content: "";
flex-grow: 1;
background: ${(props) => props.theme.invitePage.borderColor};
height: 1px;
font-size: 0px;
line-height: 0px;
margin: 0px;
}
.auth-form-fields {
width: 100%;
.password-field{
margin-bottom: 24px;
}
.email-container{
${(props) => props.registrationForm && "display:none"};
}
@media ${tablet} {
width: 100%;
}
@media ${mobile} {
width: 100%;
}
}
.password-field-wrapper {
width: 100%;
}
.greeting-container{
margin-bottom: 32px;
p{
text-align: center;
}
.back-sign-in-container {
display: flex;
align-items: center;
justify-content: center;
position: relative;
margin-bottom: 16px;
.back-button {
position: absolute;
max-width: 60px;
text-overflow: ellipsis;
overflow: hidden;
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
right: 0;
`
: css`
left: 0;
`};
display: flex;
gap: 4px;
svg {
${(props) =>
props.theme.interfaceDirection === "rtl" &&
" transform: rotate(180deg)"};
}
p {
color: ${(props) => props.theme.login.backTitle.color};
}
p:hover {
cursor: pointer;
}
}
}
}
}`;

View File

@ -1,107 +0,0 @@
// (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, { useEffect } from "react";
import PropTypes from "prop-types";
import { inject, observer } from "mobx-react";
import { Loader } from "@docspace/shared/components/loader";
import Section from "@docspace/shared/components/section";
import { combineUrl } from "@docspace/shared/utils/combineUrl";
import tryRedirectTo from "@docspace/shared/utils/tryRedirectTo";
import { EmployeeActivationStatus } from "@docspace/shared/enums";
import ConfirmRoute from "SRC_DIR/helpers/confirmRoute";
import SectionWrapper from "SRC_DIR/components/Section";
const ActivateEmail = ({ updateEmailActivationStatus, linkData }) => {
const [email, uid, key] = [
linkData.email,
linkData.uid,
linkData.confirmHeader,
];
useEffect(() => {
updateEmailActivationStatus(EmployeeActivationStatus.Activated, uid, key)
.then((res) => {
tryRedirectTo(
combineUrl(
window.ClientConfig?.proxy?.url,
`/login?confirmedEmail=${email}`,
),
);
})
.catch((error) => {
// console.log('activate email error', e);
let errorMessage = "";
if (typeof error === "object") {
errorMessage =
error?.response?.data?.error?.message ||
error?.statusText ||
error?.message ||
"";
} else {
errorMessage = error;
}
tryRedirectTo(
combineUrl(
window.ClientConfig?.proxy?.url,
`/login/error?message=${errorMessage}`,
),
);
});
}, [email, key, updateEmailActivationStatus, uid]);
// console.log('Activate email render');
return <Loader className="pageLoader" type="rombs" size="40px" />;
};
ActivateEmail.propTypes = {
location: PropTypes.object.isRequired,
};
const ActivateEmailForm = (props) => (
<SectionWrapper>
<Section.SectionBody>
<ActivateEmail {...props} />
</Section.SectionBody>
</SectionWrapper>
);
const ComponentWrapper = inject(({ userStore }) => {
const { updateEmailActivationStatus } = userStore;
return {
updateEmailActivationStatus,
};
})(observer(ActivateEmailForm));
export const Component = () => {
return (
<ConfirmRoute>
<ComponentWrapper />
</ConfirmRoute>
);
};

View File

@ -1,312 +0,0 @@
// (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, { useState } from "react";
import { withTranslation } from "react-i18next";
import { TextInput } from "@docspace/shared/components/text-input";
import { PasswordInput } from "@docspace/shared/components/password-input";
import { Button } from "@docspace/shared/components/button";
import { FieldContainer } from "@docspace/shared/components/field-container";
import { inject, observer } from "mobx-react";
import { EmployeeActivationStatus } from "@docspace/shared/enums";
import {
changePassword,
updateActivationStatus,
updateUser,
} from "@docspace/shared/api/people";
import { createPasswordHash } from "@docspace/shared/utils/common";
import { toastr } from "@docspace/shared/components/toast";
import { getPasswordErrorMessage } from "@docspace/shared/utils/getPasswordErrorMessage";
import { FormWrapper } from "@docspace/shared/components/form-wrapper";
import { StyledPage, StyledHeader } from "./StyledConfirm";
import withLoader from "../withLoader";
import {
GreetingContainer,
RegisterContainer,
StyledCreateUserContent,
} from "./StyledCreateUser";
import PortalLogo from "@docspace/shared/components/portal-logo/PortalLogo";
import GreetingUserContainer from "./GreetingUserContainer";
import ConfirmRoute from "SRC_DIR/helpers/confirmRoute";
import { AuthenticatedAction } from "SRC_DIR/helpers/enums";
import { ALLOWED_PASSWORD_CHARACTERS } from "@docspace/shared/constants";
const ActivateUserForm = (props) => {
const { t, settings, linkData, hashSettings, defaultPage, login } = props;
const emailFromLink = linkData?.email ? linkData.email : "";
const [name, setName] = useState(linkData.firstname);
const [nameValid, setNameValid] = useState(true);
const [surName, setSurName] = useState(linkData.lastname);
const [surNameValid, setSurNameValid] = useState(true);
const [password, setPassword] = useState("");
const [passwordValid, setPasswordValid] = useState(true);
const [isPasswordErrorShow, setIsPasswordErrorShow] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const onChangeName = (e) => {
setName(e.target.value);
setNameValid(true);
};
const onChangeSurName = (e) => {
setSurName(e.target.value);
setSurNameValid(true);
};
const onChangePassword = (e) => {
setPassword(e.target.value);
};
const onValidatePassword = (res) => {
setPasswordValid(res);
};
const onBlurPassword = () => {
setIsPasswordErrorShow(true);
};
const onSubmit = async () => {
setIsLoading(true);
if (!name.trim()) setNameValid(false);
if (!surName.trim()) setSurNameValid(false);
if (!password.trim()) {
setPasswordValid(false);
setIsPasswordErrorShow(true);
}
if (!nameValid || !surNameValid || !password.trim() || !passwordValid) {
setIsLoading(false);
return;
}
const hash = createPasswordHash(password, hashSettings);
const loginData = {
userName: linkData.email,
passwordHash: hash,
};
const personalData = {
firstname: name,
lastname: surName,
};
try {
await activateConfirmUser(
personalData,
loginData,
linkData.confirmHeader,
linkData.uid,
EmployeeActivationStatus.Activated,
);
setIsLoading(false);
window.location.replace(defaultPage);
} catch (error) {
//console.error(error);
setIsLoading(false);
toastr.error(error);
}
};
const activateConfirmUser = async (
personalData,
loginData,
key,
userId,
activationStatus,
) => {
const changedData = {
id: userId,
FirstName: personalData.firstname,
LastName: personalData.lastname,
};
const { userName, passwordHash } = loginData;
const res1 = await changePassword(userId, loginData.passwordHash, key);
const res2 = await updateActivationStatus(activationStatus, userId, key);
const res3 = await login(userName, passwordHash);
const res4 = await updateUser(changedData);
};
const onKeyPress = (event) => {
if (event.key === "Enter") {
onSubmit();
}
};
return (
<StyledPage>
<StyledCreateUserContent>
<StyledHeader>
<GreetingContainer>
<PortalLogo className="portal-logo" />
</GreetingContainer>
</StyledHeader>
<FormWrapper>
<RegisterContainer>
<form className="auth-form-container">
<GreetingUserContainer
emailFromLink={!!emailFromLink}
email={emailFromLink}
/>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
hasError={!nameValid}
errorMessage={t("Common:RequiredField")}
>
<TextInput
id="name"
name="name"
value={name}
placeholder={t("Common:FirstName")}
size="large"
scale={true}
tabIndex={1}
isAutoFocussed={true}
autoComplete="given-name"
onChange={onChangeName}
onKeyDown={onKeyPress}
/>
</FieldContainer>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
hasError={!surNameValid}
errorMessage={t("Common:RequiredField")}
>
<TextInput
id="surname"
name="surname"
value={surName}
placeholder={t("Common:LastName")}
size="large"
scale={true}
tabIndex={2}
autoComplete="family-name"
onChange={onChangeSurName}
onKeyDown={onKeyPress}
/>
</FieldContainer>
<FieldContainer
className="form-field password-field"
isVertical={true}
labelVisible={false}
hasError={isPasswordErrorShow && !passwordValid}
errorMessage={t("Common:IncorrectPassword")}
>
<PasswordInput
className="confirm-input"
simpleView={false}
passwordSettings={settings}
id="password"
inputName="password"
placeholder={t("Common:Password")}
type="password"
inputValue={password}
hasError={isPasswordErrorShow && !passwordValid}
size="large"
scale={true}
tabIndex={1}
autoComplete="current-password"
onChange={onChangePassword}
onValidateInput={onValidatePassword}
onBlur={onBlurPassword}
onKeyDown={onKeyPress}
tooltipPasswordTitle={`${t("Common:PasswordLimitMessage")}:`}
tooltipPasswordLength={`${t("Common:PasswordMinimumLength")}: ${
settings ? settings.minLength : 8
}`}
tooltipPasswordDigits={`${t("Common:PasswordLimitDigits")}`}
tooltipPasswordCapital={`${t("Common:PasswordLimitUpperCase")}`}
tooltipPasswordSpecial={`${t(
"Common:PasswordLimitSpecialSymbols",
)}`}
generatePasswordTitle={t("Wizard:GeneratePassword")}
tooltipAllowedCharacters={`${t("Common:AllowedCharacters")}: ${ALLOWED_PASSWORD_CHARACTERS}`}
// If need copy credentials use t("EmailAndPasswordCopiedToClipboard")
/>
</FieldContainer>
<Button
scale
className="confirm-button"
primary
size="medium"
label={t("LoginRegistryButton")}
tabIndex={5}
onClick={onSubmit}
isDisabled={isLoading}
/>
</form>
</RegisterContainer>
</FormWrapper>
</StyledCreateUserContent>
</StyledPage>
);
};
const ComponentWrapper = inject(({ authStore, settingsStore }) => {
const {
greetingSettings,
hashSettings,
defaultPage,
passwordSettings,
theme,
} = settingsStore;
return {
theme,
settings: passwordSettings,
hashSettings,
defaultPage,
login: authStore.login,
};
})(
withTranslation(["Confirm", "Common", "Wizard"])(
withLoader(observer(ActivateUserForm)),
),
);
export const Component = () => {
return (
<ConfirmRoute doAuthenticated={AuthenticatedAction.Redirect}>
<ComponentWrapper />
</ConfirmRoute>
);
};

View File

@ -1,110 +0,0 @@
// (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, { useEffect } from "react";
import { Loader } from "@docspace/shared/components/loader";
import Section from "@docspace/shared/components/section";
import { getCookie, deleteCookie } from "@docspace/shared/utils/cookie";
import { loginWithConfirmKey } from "@docspace/shared/api/user";
import { useSearchParams, useLocation } from "react-router-dom";
import { combineUrl } from "@docspace/shared/utils/combineUrl";
import { toastr } from "@docspace/shared/components/toast";
import { frameCallEvent } from "@docspace/shared/utils/common";
import SectionWrapper from "SRC_DIR/components/Section";
import ConfirmRoute from "SRC_DIR/helpers/confirmRoute";
import { AuthenticatedAction } from "SRC_DIR/helpers/enums";
const Auth = (props) => {
//console.log("Auth render");
const { linkData } = props;
let [searchParams, setSearchParams] = useSearchParams();
const location = useLocation();
useEffect(() => {
loginWithConfirmKey({
ConfirmData: {
Email: linkData.email,
Key: linkData.key,
},
})
.then((res) => {
//console.log("Login with confirm key success", res);
frameCallEvent({ event: "onAuthSuccess" });
const url = searchParams.get("referenceUrl");
const redirectUrl = getCookie("x-redirect-authorization-uri");
deleteCookie("x-redirect-authorization-uri");
if (redirectUrl) {
window.location.replace(redirectUrl);
return;
}
if (url && url.includes("oauth2")) {
const newUrl = location.search.split("referenceUrl=")[1];
window.location.replace(newUrl);
return;
}
if (url) {
try {
new URL(url);
return window.location.replace(url);
} catch {
return window.location.replace(
combineUrl(window.location.origin, url),
);
}
}
if (typeof res === "string") window.location.replace(res);
else window.location.replace("/");
})
.catch((error) => {
frameCallEvent({ event: "onAppError", data: error });
toastr.error(error);
});
});
return <Loader className="pageLoader" type="rombs" size="40px" />;
};
const AuthPage = (props) => (
<SectionWrapper>
<Section.SectionBody>
<Auth {...props} />
</Section.SectionBody>
</SectionWrapper>
);
export const Component = () => {
return (
<ConfirmRoute doAuthenticated={AuthenticatedAction.Logout}>
<AuthPage />
</ConfirmRoute>
);
};

View File

@ -1,126 +0,0 @@
// (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 PropTypes from "prop-types";
import { inject, observer } from "mobx-react";
import { Loader } from "@docspace/shared/components/loader";
import Section from "@docspace/shared/components/section";
import { combineUrl } from "@docspace/shared/utils/combineUrl";
import tryRedirectTo from "@docspace/shared/utils/tryRedirectTo";
import SectionWrapper from "SRC_DIR/components/Section";
import ConfirmRoute from "SRC_DIR/helpers/confirmRoute";
class ChangeEmail extends React.PureComponent {
componentDidMount() {
const { changeEmail, isLoaded, linkData } = this.props;
if (isLoaded) {
const { email, uid, confirmHeader } = linkData;
changeEmail(uid, email, confirmHeader)
.then((res) => {
console.log("change client email success", res);
tryRedirectTo(
combineUrl(
window.ClientConfig?.proxy?.url,
`/profile?email_change=success`,
),
);
})
.catch((error) => {
let errorMessage = "";
if (typeof error === "object") {
errorMessage =
error?.response?.data?.error?.message ||
error?.statusText ||
error?.message ||
"";
} else {
errorMessage = error;
}
console.log("change client email error", e);
tryRedirectTo(
combineUrl(
window.ClientConfig?.proxy?.url,
`/error=${errorMessage}`,
),
);
});
}
}
componentDidUpdate() {
const { changeEmail, isLoaded, linkData, defaultPage } = this.props;
if (isLoaded) {
const { email, uid, confirmHeader } = linkData;
changeEmail(uid, email, confirmHeader)
.then((res) => {
console.log("change client email success", res);
tryRedirectTo(
combineUrl(
window.ClientConfig?.proxy?.url,
`/profile?email_change=success`,
),
);
})
.catch((e) => console.log("change client email error", e));
} else {
tryRedirectTo(defaultPage);
}
}
render() {
console.log("Change email render");
return <Loader className="pageLoader" type="rombs" size="40px" />;
}
}
ChangeEmail.propTypes = {
changeEmail: PropTypes.func.isRequired,
};
const ChangeEmailForm = (props) => (
<SectionWrapper>
<Section.SectionBody>
<ChangeEmail {...props} />
</Section.SectionBody>
</SectionWrapper>
);
const ComponentWrapper = inject(({ authStore, settingsStore, userStore }) => {
const { isLoaded } = authStore;
return {
isLoaded,
changeEmail: userStore.changeEmail,
defaultPage: settingsStore.defaultPage,
};
})(observer(ChangeEmailForm));
export const Component = () => {
return (
<ConfirmRoute>
<ComponentWrapper />
</ConfirmRoute>
);
};

View File

@ -1,145 +0,0 @@
// (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, { useEffect, useState } from "react";
import { withTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import { Text } from "@docspace/shared/components/text";
import { Button } from "@docspace/shared/components/button";
import { inject, observer } from "mobx-react";
import {
StyledPage,
StyledBody,
ButtonsWrapper,
StyledContent,
} from "./StyledConfirm";
import withLoader from "../withLoader";
import { FormWrapper } from "@docspace/shared/components/form-wrapper";
import { toastr } from "@docspace/shared/components/toast";
import PortalLogo from "@docspace/shared/components/portal-logo/PortalLogo";
import { ownerChange } from "@docspace/shared/api/settings";
import { getUserFromConfirm } from "@docspace/shared/api/people";
import ConfirmRoute from "SRC_DIR/helpers/confirmRoute";
const ChangeOwnerForm = (props) => {
const { t, greetingTitle, linkData, history } = props;
const [newOwner, setNewOwner] = useState("");
const [isOwnerChanged, setIsOwnerChanged] = useState(false);
const navigate = useNavigate();
const ownerId = linkData.uid;
useEffect(() => {
const fetchData = async () => {
const confirmKey = linkData.confirmHeader;
const user = await getUserFromConfirm(ownerId, confirmKey);
setNewOwner(user?.displayName);
};
fetchData();
}, []);
const onChangeOwnerClick = async () => {
try {
await ownerChange(ownerId, linkData.confirmHeader);
setIsOwnerChanged(true);
setTimeout(() => (location.href = "/"), 10000);
} catch (error) {
toastr.error(e);
console.error(error);
}
};
const onCancelClick = () => {
navigate("/");
};
return (
<StyledPage>
<StyledContent>
<StyledBody>
<PortalLogo className="portal-logo" />
<Text fontSize="23px" fontWeight="700" className="title">
{greetingTitle}
</Text>
<FormWrapper>
{isOwnerChanged ? (
<Text>
{t("ConfirmOwnerPortalSuccessMessage", {
productName: t("Common:ProductName"),
})}
</Text>
) : (
<>
<Text className="subtitle">
{t("ConfirmOwnerPortalTitle", {
newOwner: newOwner,
productName: t("Common:ProductName"),
})}
</Text>
<ButtonsWrapper>
<Button
primary
scale
size="medium"
label={t("Common:SaveButton")}
tabIndex={2}
isDisabled={false}
onClick={onChangeOwnerClick}
/>
<Button
scale
size="medium"
label={t("Common:CancelButton")}
tabIndex={2}
isDisabled={false}
onClick={onCancelClick}
/>
</ButtonsWrapper>
</>
)}
</FormWrapper>
</StyledBody>
</StyledContent>
</StyledPage>
);
};
const ComponentWrapper = inject(({ settingsStore }) => ({
greetingTitle: settingsStore.greetingSettings,
defaultPage: settingsStore.defaultPage,
}))(
withTranslation(["Confirm", "Common"])(withLoader(observer(ChangeOwnerForm))),
);
export const Component = () => {
return (
<ConfirmRoute>
<ComponentWrapper />
</ConfirmRoute>
);
};

View File

@ -1,244 +0,0 @@
// (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, { useState, useEffect } from "react";
import { withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import { Text } from "@docspace/shared/components/text";
import { PasswordInput } from "@docspace/shared/components/password-input";
import { Button } from "@docspace/shared/components/button";
import { FieldContainer } from "@docspace/shared/components/field-container";
import { toastr } from "@docspace/shared/components/toast";
import { FormWrapper } from "@docspace/shared/components/form-wrapper";
import { createPasswordHash } from "@docspace/shared/utils/common";
import { login } from "@docspace/shared/utils/loginUtils";
import { getPasswordErrorMessage } from "@docspace/shared/utils/getPasswordErrorMessage";
import PortalLogo from "@docspace/shared/components/portal-logo/PortalLogo";
import withLoader from "../withLoader";
import { StyledPage, StyledBody, StyledContent } from "./StyledConfirm";
import ConfirmRoute from "SRC_DIR/helpers/confirmRoute";
import { ALLOWED_PASSWORD_CHARACTERS } from "@docspace/shared/constants";
const ChangePasswordForm = (props) => {
const {
t,
greetingTitle,
settings,
hashSettings,
defaultPage,
changePassword,
linkData,
getSettings,
history,
} = props;
const [password, setPassword] = useState("");
const [passwordValid, setPasswordValid] = useState(true);
const [isPasswordErrorShow, setIsPasswordErrorShow] = useState(false);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
if (!hashSettings) getSettings(true);
}, []);
const onChangePassword = (e) => {
setPassword(e.target.value);
};
const onValidatePassword = (res) => {
setPasswordValid(res);
};
const onBlurPassword = () => {
setIsPasswordErrorShow(true);
};
const onSubmit = async () => {
setIsLoading(true);
if (!password.trim()) {
setPasswordValid(false);
setIsPasswordErrorShow(true);
}
if (!passwordValid || !password.trim()) {
setIsLoading(false);
return;
}
try {
const hash = createPasswordHash(password, hashSettings);
const { email, uid, confirmHeader } = linkData;
await changePassword(uid, hash, confirmHeader);
setIsLoading(false);
toastr.success(t("ChangePasswordSuccess"));
login(email, hash).then((res) => {
const isConfirm = typeof res === "string" && res.includes("confirm");
const redirectPath = sessionStorage.getItem("referenceUrl");
if (redirectPath && !isConfirm) {
sessionStorage.removeItem("referenceUrl");
window.location.href = redirectPath;
return;
}
if (typeof res === "string") window.location.replace(res);
else window.location.replace("/");
});
} catch (error) {
let errorMessage = "";
if (typeof error === "object") {
errorMessage =
error?.response?.data?.error?.message ||
error?.statusText ||
error?.message ||
"";
} else {
errorMessage = error;
}
console.error(errorMessage);
if (errorMessage === "Invalid params") {
toastr.error(t("Common:SomethingWentWrong"));
} else {
toastr.error(t(`${errorMessage}`));
}
setIsLoading(false);
}
};
const onKeyPress = (event) => {
if (event.key === "Enter") {
onSubmit();
}
};
return (
<StyledPage>
<StyledContent>
<StyledBody>
<PortalLogo className="portal-logo" />
<Text fontSize="23px" fontWeight="700" className="title">
{greetingTitle}
</Text>
<FormWrapper>
<div className="password-form">
<Text fontSize="16px" fontWeight="600" className="subtitle">
{t("PassworResetTitle")}
</Text>
<FieldContainer
isVertical={true}
labelVisible={false}
hasError={isPasswordErrorShow && !passwordValid}
errorMessage={t("Common:IncorrectPassword")}
>
<PasswordInput
simpleView={false}
passwordSettings={settings}
id="password"
inputName="password"
placeholder={t("Common:Password")}
type="password"
inputValue={password}
hasError={isPasswordErrorShow && !passwordValid}
size="large"
scale
tabIndex={1}
autoComplete="current-password"
onChange={onChangePassword}
onValidateInput={onValidatePassword}
onBlur={onBlurPassword}
onKeyDown={onKeyPress}
tooltipPasswordTitle={`${t("Common:PasswordLimitMessage")}:`}
tooltipPasswordLength={`${t(
"Common:PasswordMinimumLength",
)}: ${settings ? settings.minLength : 8}`}
tooltipPasswordDigits={`${t("Common:PasswordLimitDigits")}`}
tooltipPasswordCapital={`${t(
"Common:PasswordLimitUpperCase",
)}`}
tooltipPasswordSpecial={`${t(
"Common:PasswordLimitSpecialSymbols",
)}`}
generatePasswordTitle={t("Wizard:GeneratePassword")}
tooltipAllowedCharacters={`${t("Common:AllowedCharacters")}: ${ALLOWED_PASSWORD_CHARACTERS}`}
/>
</FieldContainer>
</div>
<Button
primary
size="medium"
scale
label={t("Common:Create")}
tabIndex={5}
onClick={onSubmit}
isDisabled={isLoading}
/>
</FormWrapper>
</StyledBody>
</StyledContent>
</StyledPage>
);
};
const ComponentWrapper = inject(({ authStore, settingsStore, setup }) => {
const {
greetingSettings,
hashSettings,
defaultPage,
passwordSettings,
theme,
getSettings,
} = settingsStore;
const { changePassword } = setup;
return {
theme,
settings: passwordSettings,
greetingTitle: greetingSettings,
hashSettings,
defaultPage,
changePassword,
isAuthenticated: authStore.isAuthenticated,
getSettings,
};
})(
withTranslation(["Confirm", "Common", "Wizard"])(
withLoader(observer(ChangePasswordForm)),
),
);
export const Component = () => {
return (
<ConfirmRoute>
<ComponentWrapper />
</ConfirmRoute>
);
};

View File

@ -1,104 +0,0 @@
// (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, { useState } from "react";
import { withTranslation } from "react-i18next";
import { Text } from "@docspace/shared/components/text";
import { TextInput } from "@docspace/shared/components/text-input";
import { Button } from "@docspace/shared/components/button";
import { inject, observer } from "mobx-react";
import { StyledPage, StyledBody, StyledContent } from "./StyledConfirm";
import withLoader from "../withLoader";
import { FormWrapper } from "@docspace/shared/components/form-wrapper";
import PortalLogo from "@docspace/shared/components/portal-logo/PortalLogo";
import ConfirmRoute from "SRC_DIR/helpers/confirmRoute";
const ChangePhoneForm = (props) => {
const { t, greetingTitle } = props;
const [currentNumber, setCurrentNumber] = useState("+00000000000");
return (
<StyledPage>
<StyledContent>
<StyledBody>
<PortalLogo className="portal-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>
<Text>
{t("PhoneSubtitle", { productName: t("Common:ProductName") })}
</Text>
</div>
<TextInput
className="phone-input"
id="phone"
name="phone"
type="phone"
size="large"
scale={true}
isAutoFocussed={true}
tabIndex={1}
hasError={false}
guide={false}
/>
<Button
primary
scale
size="medium"
label={t("GetCode")}
tabIndex={2}
isDisabled={false}
/>
</FormWrapper>
</StyledBody>
</StyledContent>
</StyledPage>
);
};
const ComponentWrapper = inject(({ settingsStore }) => ({
greetingTitle: settingsStore.greetingSettings,
}))(withTranslation("Confirm")(withLoader(observer(ChangePhoneForm))));
export const Component = () => {
return (
<ConfirmRoute>
<ComponentWrapper />
</ConfirmRoute>
);
};

View File

@ -1,136 +0,0 @@
// (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, { useState } from "react";
import { useNavigate } from "react-router-dom";
import { Trans, withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import { Text } from "@docspace/shared/components/text";
import { Button } from "@docspace/shared/components/button";
import { Link } from "@docspace/shared/components/link";
import { toastr } from "@docspace/shared/components/toast";
import { continuePortal } from "@docspace/shared/api/portal";
import {
StyledPage,
StyledBody,
StyledContent,
ButtonsWrapper,
} from "./StyledConfirm";
import withLoader from "../withLoader";
import { FormWrapper } from "@docspace/shared/components/form-wrapper";
import PortalLogo from "@docspace/shared/components/portal-logo/PortalLogo";
import ConfirmRoute from "SRC_DIR/helpers/confirmRoute";
import { AuthenticatedAction } from "SRC_DIR/helpers/enums";
const ContinuePortal = (props) => {
const { t, greetingTitle, linkData } = props;
const [isReactivate, setIsReactivate] = useState(false);
const navigate = useNavigate();
const onRestoreClick = async () => {
try {
await continuePortal(linkData.confirmHeader);
setIsReactivate(true);
setTimeout(() => (window.location.href = "/"), 10000);
} catch (e) {
toastr.error(e);
}
};
const onCancelClick = () => {
navigate("/");
};
return (
<StyledPage>
<StyledContent>
<StyledBody>
<PortalLogo className="portal-logo" />
<Text fontSize="23px" fontWeight="700" className="title">
{greetingTitle}
</Text>
<FormWrapper>
{isReactivate ? (
<Text>
<Trans t={t} i18nKey="SuccessReactivate" ns="Confirm">
Your account has been successfully reactivated. In 10 seconds
you will be redirected to the
<Link isHovered href="/">
portal
</Link>
</Trans>
</Text>
) : (
<>
<Text className="subtitle">
{t("PortalContinueTitle", {
productName: t("Common:ProductName"),
})}
</Text>
<ButtonsWrapper>
<Button
primary
scale
size="medium"
label={t("Reactivate")}
tabIndex={1}
onClick={onRestoreClick}
/>
<Button
scale
size="medium"
label={t("Common:CancelButton")}
tabIndex={1}
onClick={onCancelClick}
/>
</ButtonsWrapper>
</>
)}
</FormWrapper>
</StyledBody>
</StyledContent>
</StyledPage>
);
};
const ComponentWrapper = inject(({ settingsStore }) => ({
greetingTitle: settingsStore.greetingSettings,
theme: settingsStore.theme,
}))(
withTranslation(["Confirm", "Common"])(withLoader(observer(ContinuePortal))),
);
export const Component = () => {
return (
<ConfirmRoute doAuthenticated={AuthenticatedAction.Logout}>
<ComponentWrapper />
</ConfirmRoute>
);
};

View File

@ -1,770 +0,0 @@
// (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 SsoReactSvg from "PUBLIC_DIR/images/sso.react.svg";
import React, { useEffect, useState, useCallback } from "react";
import { withTranslation, Trans } from "react-i18next";
import { inject, observer } from "mobx-react";
import { Button } from "@docspace/shared/components/button";
import { TextInput } from "@docspace/shared/components/text-input";
import { Text } from "@docspace/shared/components/text";
import { PasswordInput } from "@docspace/shared/components/password-input";
import { FieldContainer } from "@docspace/shared/components/field-container";
import { toastr } from "@docspace/shared/components/toast";
import { SocialButtonsGroup } from "@docspace/shared/components/social-buttons-group";
import { EmailInput } from "@docspace/shared/components/email-input";
import { FormWrapper } from "@docspace/shared/components/form-wrapper";
import {
getUserFromConfirm,
createUser,
signupOAuth,
getUserByEmail,
} from "@docspace/shared/api/people";
import {
createPasswordHash,
getOAuthToken,
getLoginLink,
} from "@docspace/shared/utils/common";
import { login } from "@docspace/shared/utils/loginUtils";
import {
ALLOWED_PASSWORD_CHARACTERS,
COOKIE_EXPIRATION_YEAR,
LANGUAGE,
PROVIDERS_DATA,
} from "@docspace/shared/constants";
import { combineUrl } from "@docspace/shared/utils/combineUrl";
import { getPasswordErrorMessage } from "@docspace/shared/utils/getPasswordErrorMessage";
import PortalLogo from "@docspace/shared/components/portal-logo/PortalLogo";
import withLoader from "../withLoader";
import { StyledPage } from "./StyledConfirm";
import {
GreetingContainer,
RegisterContainer,
StyledCreateUserContent,
} from "./StyledCreateUser";
import GreetingUserContainer from "./GreetingUserContainer";
import LanguageComboboxWrapper from "./LanguageCombobox";
import withCultureNames from "SRC_DIR/HOCs/withCultureNames";
import { setCookie } from "@docspace/shared/utils/cookie";
import ConfirmRoute from "SRC_DIR/helpers/confirmRoute";
import { AuthenticatedAction } from "SRC_DIR/helpers/enums";
const DEFAULT_ROOM_TEXT =
"<strong>{{firstName}} {{lastName}}</strong> invites you to join the room <strong>{{roomName}}</strong> for secure document collaboration.";
const DEFAULT_PORTAL_TEXT =
"<strong>{{firstName}} {{lastName}}</strong> invites you to join the room <strong>{{roomName}}</strong> for secure document collaboration.";
const RegistrationFormGreeting = ({
email,
setRegistrationForm,
type,
emailFromLink,
}) => {
const onClickBack = () => {
setRegistrationForm(false);
};
return (
<GreetingUserContainer
type={type}
emailFromLink={!!emailFromLink}
email={email}
onClickBack={onClickBack}
/>
);
};
const CreateUserForm = (props) => {
const {
settings,
t,
providers,
isDesktop,
linkData,
roomData,
capabilities,
currentColorScheme,
userNameRegex,
defaultPage,
cultures,
i18n,
} = props;
const currentCultureName = i18n.language;
const inputRef = React.useRef(null);
const emailFromLink = linkData?.email ? linkData.email : "";
const roomName = roomData?.title;
const roomId = roomData?.roomId;
const [email, setEmail] = useState(emailFromLink);
const [emailValid, setEmailValid] = useState(true);
const [emailErrorText, setEmailErrorText] = useState("");
const [password, setPassword] = useState("");
const [passwordValid, setPasswordValid] = useState(true);
const [fname, setFname] = useState("");
const [fnameValid, setFnameValid] = useState(true);
const [sname, setSname] = useState("");
const [snameValid, setSnameValid] = useState(true);
const [isLoading, setIsLoading] = useState(false);
const [errorText, setErrorText] = useState("");
const [user, setUser] = useState("");
const [isEmailErrorShow, setIsEmailErrorShow] = useState(false);
const [isPasswordErrorShow, setIsPasswordErrorShow] = useState(false);
const [registrationForm, setRegistrationForm] = useState(emailFromLink);
const focusInput = () => {
if (inputRef) {
inputRef.current.focus();
}
};
const nameRegex = new RegExp(userNameRegex, "gu");
useEffect(() => {
const { linkData } = props;
const fetchData = async () => {
if (linkData.type === "LinkInvite") {
const uid = linkData.uid;
const confirmKey = linkData.confirmHeader;
const user = await getUserFromConfirm(uid, confirmKey);
setUser(user);
}
window.authCallback = authCallback;
focusInput();
};
fetchData();
}, []);
const onContinue = async () => {
const { linkData } = props;
if (!emailValid) {
setIsEmailErrorShow(true);
return;
}
setIsLoading(true);
const headerKey = linkData.confirmHeader;
try {
const toBinaryStr = (str) => {
const encoder = new TextEncoder();
const charCodes = encoder.encode(str);
return String.fromCharCode(...charCodes);
};
const loginData = window.btoa(
toBinaryStr(
JSON.stringify({
type: "invitation",
email,
roomName,
firstName: user.firstName,
lastName: user.lastName,
linkData: linkData,
}),
),
);
await getUserByEmail(email, headerKey);
setCookie(LANGUAGE, currentCultureName, {
"max-age": COOKIE_EXPIRATION_YEAR,
});
const finalUrl = roomId
? `/rooms/shared/${roomId}/filter?folder=${roomId}`
: defaultPage;
if (roomId) {
sessionStorage.setItem("referenceUrl", finalUrl);
}
window.location.href = combineUrl(
window.ClientConfig?.proxy?.url,
"/login",
`?loginData=${loginData}`,
);
} catch (err) {
console.error(err);
const status = err?.response?.status;
const isNotExistUser = status === 404;
if (isNotExistUser) {
setRegistrationForm(true);
}
}
setIsLoading(false);
};
const onSubmit = () => {
const { linkData, hashSettings } = props;
const type = parseInt(linkData.emplType);
setIsLoading(true);
setErrorText("");
let hasError = false;
if (!fname.trim() || !fnameValid) {
hasError = true;
setFnameValid(!hasError);
}
if (!sname.trim() || !snameValid) {
hasError = true;
setSnameValid(!hasError);
}
if (!passwordValid || !password.trim()) {
hasError = true;
setPasswordValid(!hasError);
setIsPasswordErrorShow(true);
}
if (hasError) {
setIsLoading(false);
return false;
}
const hash = createPasswordHash(password, hashSettings);
const loginData = {
userName: email,
passwordHash: hash,
};
const personalData = {
firstname: fname.trim(),
lastname: sname.trim(),
email: email,
cultureName: currentCultureName,
};
if (!!type) {
personalData.type = type;
}
if (!!linkData.key) {
personalData.key = linkData.key;
}
const headerKey = linkData.confirmHeader;
createConfirmUser(personalData, loginData, headerKey).catch((error) => {
let errorMessage = "";
if (typeof error === "object") {
errorMessage =
error?.response?.data?.error?.message ||
error?.statusText ||
error?.message ||
"";
} else {
errorMessage = error;
}
console.error("confirm error", errorMessage);
setIsEmailErrorShow(true);
setEmailErrorText(errorMessage);
setEmailValid(false);
setIsLoading(false);
});
};
const authCallback = (profile) => {
const signupAccount = {
EmployeeType: linkData.emplType || null,
Email: linkData.email,
Key: linkData.key,
SerializedProfile: profile,
culture: currentCultureName,
};
const confirmKey = linkData.confirmHeader;
signupOAuth(signupAccount, confirmKey)
.then(() => {
const url = roomData.roomId
? `/rooms/shared/${roomData.roomId}/filter?folder=${roomData.roomId}/`
: defaultPage;
window.location.replace(url);
})
.catch((e) => {
toastr.error(e);
});
};
const createConfirmUser = async (registerData, loginData, key) => {
const { defaultPage } = props;
const fromInviteLink =
linkData.type === "LinkInvite" || linkData.type === "EmpInvite"
? true
: false;
const data = Object.assign({ fromInviteLink }, registerData, loginData);
await createUser(data, key);
const { userName, passwordHash } = loginData;
const res = await login(userName, passwordHash);
//console.log({ res });
const finalUrl = roomData.roomId
? `/rooms/shared/${roomData.roomId}/filter?folder=${roomData.roomId}`
: defaultPage;
const isConfirm = typeof res === "string" && res.includes("confirm");
if (isConfirm) {
sessionStorage.setItem("referenceUrl", finalUrl);
return window.location.replace(typeof res === "string" ? res : "/");
}
window.location.replace(finalUrl);
};
const onChangeEmail = (e) => {
setEmail(e.target.value);
setIsEmailErrorShow(false);
};
const onChangeFname = (e) => {
setFname(e.target.value);
setFnameValid(nameRegex.test(e.target.value.trim()));
setErrorText("");
};
const onChangeSname = (e) => {
setSname(e.target.value);
setSnameValid(nameRegex.test(e.target.value.trim()));
setErrorText("");
};
const onChangePassword = (e) => {
setPassword(e.target.value);
setErrorText("");
setIsPasswordErrorShow(false);
};
const onKeyPress = (event) => {
if (event.key === "Enter") {
registrationForm ? onSubmit() : onContinue();
}
};
const onValidatePassword = (res) => {
setPasswordValid(res);
};
const onBlurEmail = () => {
setIsEmailErrorShow(true);
};
const onBlurPassword = () => {
setIsPasswordErrorShow(true);
};
const onSocialButtonClick = useCallback((e) => {
const { target } = e;
let targetElement = target;
if (!(targetElement instanceof HTMLButtonElement) && target.parentElement) {
targetElement = target.parentElement;
}
const providerName = targetElement.dataset.providername;
const url = targetElement.dataset.url || "";
try {
const tokenGetterWin = isDesktop
? (window.location.href = url)
: window.open(
url,
"login",
"width=800,height=500,status=no,toolbar=no,menubar=no,resizable=yes,scrollbars=no",
);
getOAuthToken(tokenGetterWin).then((code) => {
const token = window.btoa(
JSON.stringify({
auth: providerName,
mode: "popup",
callback: "authCallback",
}),
);
tokenGetterWin.location.href = getLoginLink(token, code);
});
} catch (err) {
console.log(err);
}
}, []);
const oauthDataExists = () => {
if (!capabilities?.oauthEnabled) return false;
let existProviders = 0;
providers && providers.length > 0;
providers.map((item) => {
if (!PROVIDERS_DATA[item.provider]) return;
existProviders++;
});
return !!existProviders;
};
const ssoExists = () => {
if (capabilities?.ssoUrl) return true;
else return false;
};
const onValidateEmail = (res) => {
setEmailValid(res.isValid);
setEmailErrorText(res.errors[0]);
};
const ssoProps = ssoExists()
? {
ssoUrl: capabilities?.ssoUrl,
ssoLabel: capabilities?.ssoLabel,
ssoSVG: SsoReactSvg,
}
: {};
return (
<StyledPage>
<LanguageComboboxWrapper
cultures={cultures}
currentCultureName={currentCultureName}
/>
<StyledCreateUserContent>
<GreetingContainer>
<PortalLogo className="portal-logo" />
{linkData.type === "LinkInvite" && (
<div className="tooltip">
<Text fontSize="16px">
{roomName ? (
<Trans
t={t}
i18nKey="InvitationToRoom"
ns="Common"
defaults={DEFAULT_ROOM_TEXT}
values={{
firstName: user.firstName,
lastName: user.lastName,
...(roomName
? { roomName }
: { spaceAddress: window.location.host }),
}}
components={{
1: <Text fontWeight={600} as="strong" fontSize="16px" />,
}}
/>
) : (
<Trans
t={t}
i18nKey="InvitationToPortal"
ns="Common"
defaults={DEFAULT_PORTAL_TEXT}
values={{
firstName: user.firstName,
lastName: user.lastName,
productName: t("Common:ProductName"),
...(roomName
? { roomName }
: { spaceAddress: window.location.host }),
}}
components={{
1: <Text fontWeight={600} as="strong" fontSize="16px" />,
}}
/>
)}
</Text>
</div>
)}
</GreetingContainer>
<FormWrapper>
<RegisterContainer registrationForm={registrationForm}>
<div className="auth-form-fields">
<div className="email-container">
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
hasError={isEmailErrorShow && !emailValid}
errorMessage={
emailErrorText
? t(`Common:${emailErrorText}`)
: t("Common:RequiredField")
}
>
<EmailInput
id="login"
name="login"
type="email"
hasError={isEmailErrorShow && !emailValid}
value={email}
placeholder={t("Common:Email")}
size="large"
scale={true}
isAutoFocussed={true}
tabIndex={1}
isDisabled={isLoading || !!emailFromLink}
autoComplete="username"
onChange={onChangeEmail}
onBlur={onBlurEmail}
onValidateInput={onValidateEmail}
forwardedRef={inputRef}
onKeyDown={onKeyPress}
/>
</FieldContainer>
<Button
className="login-button"
primary
size="medium"
scale={true}
label={t("Common:ContinueButton")}
tabIndex={1}
isDisabled={isLoading}
isLoading={isLoading}
onClick={onContinue}
/>
</div>
{registrationForm && (
<div>
<RegistrationFormGreeting
email={email}
setRegistrationForm={setRegistrationForm}
type={linkData.type}
emailFromLink={emailFromLink}
/>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
hasError={!fnameValid}
errorMessage={
errorText
? errorText
: fname.trim().length === 0
? t("Common:RequiredField")
: t("Common:IncorrectFirstName")
}
>
<TextInput
id="first-name"
name="first-name"
type="text"
hasError={!fnameValid}
value={fname}
placeholder={t("Common:FirstName")}
size="large"
scale={true}
tabIndex={1}
isDisabled={isLoading}
onChange={onChangeFname}
onKeyDown={onKeyPress}
isAutoFocussed
/>
</FieldContainer>
<FieldContainer
className="form-field"
isVertical={true}
labelVisible={false}
hasError={!snameValid}
errorMessage={
errorText
? errorText
: sname.trim().length === 0
? t("Common:RequiredField")
: t("Common:IncorrectLastName")
}
>
<TextInput
id="last-name"
name="last-name"
type="text"
hasError={!snameValid}
value={sname}
placeholder={t("Common:LastName")}
size="large"
scale={true}
tabIndex={1}
isDisabled={isLoading}
onChange={onChangeSname}
onKeyDown={onKeyPress}
/>
</FieldContainer>
<FieldContainer
className="form-field password-field"
isVertical={true}
labelVisible={false}
hasError={isPasswordErrorShow && !passwordValid}
errorMessage={t("Common:IncorrectPassword")}
>
<PasswordInput
simpleView={false}
hideNewPasswordButton
showCopyLink={false}
passwordSettings={settings}
id="password"
inputName="password"
placeholder={t("Common:Password")}
type="password"
hasError={isPasswordErrorShow && !passwordValid}
inputValue={password}
size="large"
scale={true}
tabIndex={1}
isDisabled={isLoading}
autoComplete="current-password"
onChange={onChangePassword}
onBlur={onBlurPassword}
onKeyDown={onKeyPress}
onValidateInput={onValidatePassword}
tooltipPasswordTitle={`${t(
"Common:PasswordLimitMessage",
)}:`}
tooltipPasswordLength={`${t(
"Common:PasswordMinimumLength",
)}: ${settings ? settings.minLength : 8}`}
tooltipPasswordDigits={`${t(
"Common:PasswordLimitDigits",
)}`}
tooltipPasswordCapital={`${t(
"Common:PasswordLimitUpperCase",
)}`}
tooltipPasswordSpecial={`${t(
"Common:PasswordLimitSpecialSymbols",
)}`}
generatePasswordTitle={t("Wizard:GeneratePassword")}
tooltipAllowedCharacters={`${t("Common:AllowedCharacters")}: ${ALLOWED_PASSWORD_CHARACTERS}`}
/>
</FieldContainer>
<Button
className="login-button"
primary
size="medium"
scale={true}
label={
isLoading ? t("Common:LoadingProcessing") : t("SignUp")
}
tabIndex={1}
isDisabled={isLoading}
isLoading={isLoading}
onClick={onSubmit}
/>
</div>
)}
</div>
{!emailFromLink && (oauthDataExists() || ssoExists()) && (
<>
<div className="line">
<Text className="or-label">{t("Common:orContinueWith")}</Text>
</div>
<SocialButtonsGroup
providers={providers}
onClick={onSocialButtonClick}
t={t}
isDisabled={isLoading}
{...ssoProps}
/>
</>
)}
</RegisterContainer>
</FormWrapper>
</StyledCreateUserContent>
</StyledPage>
);
};
const ComponentWrapper = inject(({ settingsStore, authStore }) => {
const { providers, thirdPartyLogin, capabilities } = authStore;
const {
passwordSettings,
hashSettings,
defaultPage,
getSettings,
getPortalPasswordSettings,
currentColorScheme,
userNameRegex,
cultures,
} = settingsStore;
return {
settings: passwordSettings,
hashSettings,
defaultPage,
getSettings,
getPortalPasswordSettings,
thirdPartyLogin,
providers,
capabilities,
currentColorScheme,
userNameRegex,
cultures,
};
})(
withCultureNames(
withTranslation(["Confirm", "Common", "Wizard"])(
withLoader(observer(CreateUserForm)),
),
),
);
export const Component = () => {
return (
<ConfirmRoute doAuthenticated={AuthenticatedAction.None}>
<ComponentWrapper />
</ConfirmRoute>
);
};

View File

@ -1,143 +0,0 @@
// (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, { useState } from "react";
import { useNavigate } from "react-router-dom";
import { Trans, withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import { Text } from "@docspace/shared/components/text";
import { Button } from "@docspace/shared/components/button";
import { Link } from "@docspace/shared/components/link";
import { toastr } from "@docspace/shared/components/toast";
import { suspendPortal } from "@docspace/shared/api/portal";
import {
StyledPage,
StyledBody,
StyledContent,
ButtonsWrapper,
} from "./StyledConfirm";
import withLoader from "../withLoader";
import { FormWrapper } from "@docspace/shared/components/form-wrapper";
import PortalLogo from "@docspace/shared/components/portal-logo/PortalLogo";
import ConfirmRoute from "SRC_DIR/helpers/confirmRoute";
import { AuthenticatedAction } from "SRC_DIR/helpers/enums";
const DeactivatePortal = (props) => {
const { t, greetingTitle, linkData, companyInfoSettingsData } = props;
const [isDeactivate, setIsDeactivate] = useState(false);
const navigate = useNavigate();
const url = companyInfoSettingsData?.site
? companyInfoSettingsData.site
: "https://onlyoffice.com";
const onDeactivateClick = async () => {
try {
await suspendPortal(linkData.confirmHeader);
setIsDeactivate(true);
setTimeout(() => (window.location.href = url), 10000);
} catch (e) {
toastr.error(e);
}
};
const onCancelClick = () => {
navigate("/");
};
return (
<StyledPage>
<StyledContent>
<StyledBody>
<PortalLogo className="portal-logo" />
<Text fontSize="23px" fontWeight="700" className="title">
{greetingTitle}
</Text>
<FormWrapper>
{isDeactivate ? (
<Text>
<Trans t={t} i18nKey="SuccessDeactivate" ns="Confirm">
Your account has been successfully deactivated. In 10 seconds
you will be redirected to the
<Link isHovered href={url}>
site
</Link>
</Trans>
</Text>
) : (
<>
<Text className="subtitle">
{t("PortalDeactivateTitle", {
productName: t("Common:ProductName"),
})}
</Text>
<ButtonsWrapper>
<Button
scale
primary
size="medium"
label={t("Settings:Deactivate")}
tabIndex={1}
onClick={onDeactivateClick}
/>
<Button
scale
size="medium"
label={t("Common:CancelButton")}
tabIndex={1}
onClick={onCancelClick}
/>
</ButtonsWrapper>
</>
)}
</FormWrapper>
</StyledBody>
</StyledContent>
</StyledPage>
);
};
const ComponentWrapper = inject(({ settingsStore }) => ({
greetingTitle: settingsStore.greetingSettings,
theme: settingsStore.theme,
companyInfoSettingsData: settingsStore.companyInfoSettingsData,
}))(
withTranslation(["Confirm", "Settings", "Common"])(
withLoader(observer(DeactivatePortal)),
),
);
export const Component = () => {
return (
<ConfirmRoute doAuthenticated={AuthenticatedAction.Logout}>
<ComponentWrapper />
</ConfirmRoute>
);
};

View File

@ -1,168 +0,0 @@
// (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, { useState } from "react";
import { withTranslation, Trans } from "react-i18next";
import { Text } from "@docspace/shared/components/text";
import { Button } from "@docspace/shared/components/button";
import { Link } from "@docspace/shared/components/link";
import { inject, observer } from "mobx-react";
import { deleteSelf } from "@docspace/shared/api/people";
import { toastr } from "@docspace/shared/components/toast";
import { StyledPage, StyledBody, StyledContent } from "./StyledConfirm";
import withLoader from "../withLoader";
import { FormWrapper } from "@docspace/shared/components/form-wrapper";
import PortalLogo from "@docspace/shared/components/portal-logo/PortalLogo";
import ConfirmRoute from "SRC_DIR/helpers/confirmRoute";
const ProfileRemoveForm = (props) => {
const { t, greetingTitle, linkData, legalTerms, currentColorScheme } = props;
const [isProfileDeleted, setIsProfileDeleted] = useState(false);
const [isLoading, setIsLoading] = useState(false);
console.log(legalTerms);
const onDeleteProfile = () => {
setIsLoading(true);
deleteSelf(linkData.confirmHeader)
.then((res) => {
setIsLoading(false);
setIsProfileDeleted(true);
})
.catch((e) => {
setIsLoading(false);
toastr.error(e);
});
};
if (isProfileDeleted) {
return (
<StyledPage>
<StyledContent>
<StyledBody style={{ whiteSpace: "pre-wrap" }}>
<PortalLogo className="portal-logo" />
<Text fontSize="23px" fontWeight="700" className="title">
{t("DeleteProfileSuccessMessage")}
</Text>
<Text fontSize="16px" fontWeight="600" className="confirm-subtitle">
{t("DeleteProfileSuccessDescription", {
productName: t("Common:ProductName"),
})}
<Trans
i18nKey="DeleteProfileSuccessMessageInfo"
ns="Confirm"
t={t}
>
Please check our
<Link
fontSize="16px"
fontWeight="600"
type="page"
href={legalTerms}
color={currentColorScheme?.main?.accent}
target="_blank"
>
Privacy policy
</Link>
to learn more about deleting your account and associated data.
</Trans>
</Text>
</StyledBody>
</StyledContent>
</StyledPage>
);
}
return (
<StyledPage>
<StyledContent>
<StyledBody>
<PortalLogo className="portal-logo" />
<Text fontSize="23px" fontWeight="700" className="title">
{greetingTitle}
</Text>
<FormWrapper>
<div className="subtitle">
<Text
fontSize="16px"
fontWeight="600"
className="delete-profile-confirm"
>
{t("DeleteProfileConfirmation")}
</Text>
<Text>
<Trans
i18nKey="DeleteProfileConfirmationInfo"
ns="Confirm"
t={t}
>
By clicking \"Disable my account\" you agree with our Privacy
policy
<Link
type="page"
href={legalTerms}
color={currentColorScheme?.main?.accent}
target="_blank"
>
Privacy policy.
</Link>
</Trans>
</Text>
</div>
<Button
primary
scale
size="medium"
label={t("DeleteProfileBtn")}
tabIndex={1}
isDisabled={isLoading}
onClick={onDeleteProfile}
/>
</FormWrapper>
</StyledBody>
</StyledContent>
</StyledPage>
);
};
const ComponentWrapper = inject(({ settingsStore }) => ({
greetingTitle: settingsStore.greetingSettings,
theme: settingsStore.theme,
legalTerms: settingsStore.legalTerms,
currentColorScheme: settingsStore.currentColorScheme,
}))(withTranslation("Confirm")(withLoader(observer(ProfileRemoveForm))));
export const Component = () => {
return (
<ConfirmRoute>
<ComponentWrapper />
</ConfirmRoute>
);
};

View File

@ -1,139 +0,0 @@
// (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, { useState } from "react";
import { useNavigate } from "react-router-dom";
import { withTranslation, Trans } from "react-i18next";
import { inject, observer } from "mobx-react";
import { Text } from "@docspace/shared/components/text";
import { Button } from "@docspace/shared/components/button";
import { Link } from "@docspace/shared/components/link";
import { toastr } from "@docspace/shared/components/toast";
import { deletePortal } from "@docspace/shared/api/portal";
import {
StyledPage,
StyledBody,
StyledContent,
ButtonsWrapper,
} from "./StyledConfirm";
import withLoader from "../withLoader";
import { FormWrapper } from "@docspace/shared/components/form-wrapper";
import PortalLogo from "@docspace/shared/components/portal-logo/PortalLogo";
import ConfirmRoute from "SRC_DIR/helpers/confirmRoute";
const RemovePortal = (props) => {
const { t, greetingTitle, linkData, companyInfoSettingsData } = props;
const [isRemoved, setIsRemoved] = useState(false);
const url = companyInfoSettingsData?.site
? companyInfoSettingsData.site
: "https://onlyoffice.com";
const navigate = useNavigate();
const onDeleteClick = async () => {
try {
const res = await deletePortal(linkData.confirmHeader);
setIsRemoved(true);
setTimeout(() => (location.href = res ? res : url), 10000);
} catch (e) {
toastr.error(e);
}
};
const onCancelClick = () => {
navigate("/");
};
return (
<StyledPage>
<StyledContent>
<StyledBody>
<PortalLogo className="portal-logo" />
<Text fontSize="23px" fontWeight="700" className="title">
{greetingTitle}
</Text>
<FormWrapper>
{isRemoved ? (
<Text>
<Trans t={t} i18nKey="SuccessRemoved" ns="Confirm">
Your account has been successfully removed. In 10 seconds you
will be redirected to the
<Link isHovered href={url}>
site
</Link>
</Trans>
</Text>
) : (
<>
<Text className="subtitle">
{t("PortalRemoveTitle", {
productName: t("Common:ProductName"),
})}
</Text>
<ButtonsWrapper>
<Button
primary
scale
size="medium"
label={t("Common:Delete")}
tabIndex={1}
onClick={onDeleteClick}
/>
<Button
scale
size="medium"
label={t("Common:CancelButton")}
tabIndex={1}
onClick={onCancelClick}
/>
</ButtonsWrapper>
</>
)}
</FormWrapper>
</StyledBody>
</StyledContent>
</StyledPage>
);
};
const ComponentWrapper = inject(({ settingsStore }) => ({
greetingTitle: settingsStore.greetingSettings,
theme: settingsStore.theme,
companyInfoSettingsData: settingsStore.companyInfoSettingsData,
}))(withTranslation(["Confirm", "Common"])(withLoader(observer(RemovePortal))));
export const Component = () => {
return (
<ConfirmRoute>
<ComponentWrapper />
</ConfirmRoute>
);
};

View File

@ -1,361 +0,0 @@
// (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, { useCallback, useEffect, useState } from "react";
import { Trans, withTranslation } from "react-i18next";
import styled from "styled-components";
import { useNavigate } from "react-router-dom";
import { Button } from "@docspace/shared/components/button";
import { TextInput } from "@docspace/shared/components/text-input";
import { FieldContainer } from "@docspace/shared/components/field-container";
import { Text } from "@docspace/shared/components/text";
import { inject, observer } from "mobx-react";
import { Box } from "@docspace/shared/components/box";
import withLoader from "../withLoader";
import { toastr } from "@docspace/shared/components/toast";
import ErrorContainer from "@docspace/shared/components/error-container/ErrorContainer";
import { mobile, tablet } from "@docspace/shared/utils";
import { Link } from "@docspace/shared/components/link";
import { FormWrapper } from "@docspace/shared/components/form-wrapper";
import PortalLogo from "@docspace/shared/components/portal-logo/PortalLogo";
import { StyledPage, StyledContent } from "./StyledConfirm";
import {
getTfaSecretKeyAndQR,
validateTfaCode,
} from "@docspace/shared/api/settings";
import { loginWithTfaCode } from "@docspace/shared/api/user";
import { combineUrl } from "@docspace/shared/utils/combineUrl";
import ConfirmRoute from "SRC_DIR/helpers/confirmRoute";
const StyledForm = styled(Box)`
margin: 56px auto;
display: flex;
flex: 1fr 1fr;
gap: 80px;
flex-direction: row;
justify-content: center;
@media ${tablet} {
display: flex;
flex-direction: column;
align-items: center;
gap: 32px;
}
@media ${mobile} {
margin: 0 auto;
flex-direction: column;
gap: 0px;
padding-inline-end: 8px;
}
.app-code-wrapper {
width: 100%;
@media ${tablet} {
flex-direction: column;
}
}
.portal-logo {
padding-bottom: 40px;
@media ${tablet} {
display: flex;
align-items: center;
justify-content: center;
}
}
.set-app-description {
width: 100%;
max-width: 500px;
}
.set-app-title {
margin-bottom: 14px;
}
.set-app-text {
margin-top: 14px;
}
.qrcode-wrapper {
display: flex;
align-items: center;
justify-content: center;
padding: 0px 80px;
border-radius: 6px;
margin-bottom: 32px;
@media ${mobile} {
display: none;
}
}
.app-code-continue-btn {
margin-top: 8px;
}
`;
const PROXY_BASE_URL = combineUrl(window.ClientConfig?.proxy?.url, "/profile");
const TfaActivationForm = withLoader((props) => {
const {
t,
secretKey,
qrCode,
location,
currentColorScheme,
} = props;
const navigate = useNavigate();
const [code, setCode] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const onSubmit = async () => {
try {
const { user, hash } = (location && location.state) || {};
const { linkData } = props;
setIsLoading(true);
if (user && hash) {
await loginWithTfaCode(user, hash, code);
} else {
await validateTfaCode(code, linkData.confirmHeader);
}
// const referenceUrl = sessionStorage.getItem("referenceUrl");
// if (referenceUrl) {
// sessionStorage.removeItem("referenceUrl");
// }
// window.location.replace(referenceUrl || defaultPage);
navigate(PROXY_BASE_URL, {
state: { openBackupCodesDialog: true },
});
} catch (err) {
let errorMessage = "";
if (typeof err === "object") {
errorMessage =
err?.response?.data?.error?.message ||
err?.statusText ||
err?.message ||
"";
} else {
errorMessage = err;
}
setError(errorMessage);
toastr.error(errorMessage);
} finally {
setIsLoading(false);
}
};
const onKeyPress = (target) => {
if (target.code === "Enter" || target.code === "NumpadEnter") onSubmit();
};
return (
<StyledPage>
<StyledContent>
<StyledForm className="set-app-container">
<Box className="set-app-description" marginProp="0 0 32px 0">
<PortalLogo className="portal-logo" />
<Text isBold fontSize="14px" className="set-app-title">
{t("SetAppTitle")}
</Text>
<Trans
t={t}
i18nKey="SetAppDescription"
ns="Confirm"
productName={t("Common:ProductName")}
>
The two-factor authentication is enabled to provide additional
portal security. Configure your authenticator application to
continue work on the portal. For example you could use Google
Authenticator for
<Link
color={currentColorScheme?.main?.accent}
href={props.tfaAndroidAppUrl}
target="_blank"
>
Android
</Link>
and{" "}
<Link
color={currentColorScheme?.main?.accent}
href={props.tfaIosAppUrl}
target="_blank"
>
iOS
</Link>{" "}
or Authenticator for{" "}
<Link
color={currentColorScheme?.main?.accent}
href={props.tfaWinAppUrl}
target="_blank"
>
Windows Phone
</Link>{" "}
.
</Trans>
<Text className="set-app-text">
<Trans
t={t}
i18nKey="SetAppInstallDescription"
ns="Confirm"
key={secretKey}
>
To connect your apllication scan the QR code or manually enter
your secret key <strong>{{ secretKey }}</strong> then enter
6-digit code from your application in the field below.
</Trans>
</Text>
</Box>
<FormWrapper>
<Box
displayProp="flex"
flexDirection="column"
className="app-code-wrapper"
>
<div className="qrcode-wrapper">
<img
src={qrCode}
height="180px"
width="180px"
alt="QR-code"
></img>
</div>
<Box className="app-code-input">
<FieldContainer
labelVisible={false}
hasError={error ? true : false}
errorMessage={error}
>
<TextInput
id="code"
name="code"
type="text"
size="large"
scale
isAutoFocussed
tabIndex={1}
placeholder={t("EnterCodePlaceholder")}
isDisabled={isLoading}
maxLength={6}
onChange={(e) => {
setCode(e.target.value);
setError("");
}}
value={code}
hasError={error ? true : false}
onKeyDown={onKeyPress}
/>
</FieldContainer>
</Box>
<Box className="app-code-continue-btn">
<Button
scale
primary
size="medium"
tabIndex={3}
label={
isLoading
? t("Common:LoadingProcessing")
: t("SetAppButton")
}
isDisabled={!code.length || isLoading}
isLoading={isLoading}
onClick={onSubmit}
/>
</Box>
</Box>
</FormWrapper>
</StyledForm>
</StyledContent>
</StyledPage>
);
});
const TfaActivationWrapper = (props) => {
const { linkData, setIsLoaded, setIsLoading } = props;
const [secretKey, setSecretKey] = useState("");
const [qrCode, setQrCode] = useState("");
const [error, setError] = useState(null);
const getSecretKeyAndQRAction = useCallback(async () => {
try {
setIsLoading(true);
const confirmKey = linkData.confirmHeader;
const res = await getTfaSecretKeyAndQR(confirmKey);
const { manualEntryKey, qrCodeSetupImageUrl } = res;
setSecretKey(manualEntryKey);
setQrCode(qrCodeSetupImageUrl);
} catch (e) {
setError(e.error);
toastr.error(e);
}
setIsLoaded(true);
setIsLoading(false);
});
useEffect(() => {
getSecretKeyAndQRAction();
}, []);
return error ? (
<ErrorContainer bodyText={error} />
) : (
<TfaActivationForm secretKey={secretKey} qrCode={qrCode} {...props} />
);
};
const ComponentWrapper = inject(({ settingsStore, confirm, tfaStore }) => ({
setIsLoaded: confirm.setIsLoaded,
setIsLoading: confirm.setIsLoading,
tfaAndroidAppUrl: tfaStore.tfaAndroidAppUrl,
tfaIosAppUrl: tfaStore.tfaIosAppUrl,
tfaWinAppUrl: tfaStore.tfaWinAppUrl,
currentColorScheme: settingsStore.currentColorScheme,
}))(withTranslation(["Confirm", "Common"])(observer(TfaActivationWrapper)));
export const Component = () => {
return (
<ConfirmRoute>
<ComponentWrapper />
</ConfirmRoute>
);
};

View File

@ -1,222 +0,0 @@
// (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, { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import { withTranslation } from "react-i18next";
import styled from "styled-components";
import { Button } from "@docspace/shared/components/button";
import { TextInput } from "@docspace/shared/components/text-input";
import { FieldContainer } from "@docspace/shared/components/field-container";
import { Text } from "@docspace/shared/components/text";
import { inject, observer } from "mobx-react";
import { Box } from "@docspace/shared/components/box";
import { toastr } from "@docspace/shared/components/toast";
import withLoader from "../withLoader";
import { mobile } from "@docspace/shared/utils";
import { FormWrapper } from "@docspace/shared/components/form-wrapper";
import PortalLogo from "@docspace/shared/components/portal-logo/PortalLogo";
import { StyledPage, StyledContent } from "./StyledConfirm";
import { validateTfaCode } from "@docspace/shared/api/settings";
import { loginWithTfaCode } from "@docspace/shared/api/user";
import ConfirmRoute from "SRC_DIR/helpers/confirmRoute";
const StyledForm = styled(Box)`
margin: 56px auto;
display: flex;
flex-direction: column;
flex: 1fr;
@media ${mobile} {
margin: 0 auto;
width: 100%;
}
.portal-logo {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
padding-bottom: 40px;
}
.app-code-wrapper {
width: 100%;
}
.app-code-text {
margin-bottom: 8px;
}
.app-code-continue-btn {
margin-top: 8px;
}
`;
const TfaAuthForm = withLoader((props) => {
const { t } = props;
const [code, setCode] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const location = useLocation();
const onSubmit = async () => {
try {
const { user, hash } = (location && location.state) || {};
const { linkData, defaultPage } = props;
setIsLoading(true);
if (user && hash) {
await loginWithTfaCode(user, hash, code);
} else {
await validateTfaCode(code, linkData.confirmHeader);
}
const referenceUrl = sessionStorage.getItem("referenceUrl");
if (referenceUrl) {
sessionStorage.removeItem("referenceUrl");
}
window.location.replace(referenceUrl || defaultPage);
} catch (err) {
let errorMessage = "";
if (typeof err === "object") {
errorMessage =
err?.response?.data?.error?.message ||
err?.statusText ||
err?.message ||
"";
} else {
errorMessage = err;
}
setError(errorMessage);
toastr.error(errorMessage);
} finally {
setIsLoading(false);
}
};
const onKeyPress = (target) => {
if (target.code === "Enter" || target.code === "NumpadEnter") onSubmit();
};
return (
<StyledPage>
<StyledContent>
<StyledForm className="app-code-container">
<PortalLogo className="portal-logo" />
<FormWrapper>
<Box className="app-code-description" marginProp="0 0 32px 0">
<Text isBold fontSize="14px" className="app-code-text">
{t("EnterAppCodeTitle")}
</Text>
<Text>{t("EnterAppCodeDescription")}</Text>
</Box>
<Box
displayProp="flex"
flexDirection="column"
className="app-code-wrapper"
>
<Box className="app-code-input">
<FieldContainer
labelVisible={false}
hasError={error ? true : false}
errorMessage={error}
>
<TextInput
id="code"
name="code"
type="text"
size="large"
scale
isAutoFocussed
tabIndex={1}
placeholder={t("EnterCodePlaceholder")}
isDisabled={isLoading}
maxLength={6}
onChange={(e) => {
setCode(e.target.value);
setError("");
}}
value={code}
hasError={error ? true : false}
onKeyDown={onKeyPress}
/>
</FieldContainer>
</Box>
<Box className="app-code-continue-btn">
<Button
scale
primary
size="medium"
tabIndex={3}
label={
isLoading
? t("Common:LoadingProcessing")
: t("Common:ContinueButton")
}
isDisabled={!code.length || isLoading}
isLoading={isLoading}
onClick={onSubmit}
/>
</Box>
</Box>
</FormWrapper>
</StyledForm>
</StyledContent>
</StyledPage>
);
});
const TfaAuthFormWrapper = (props) => {
const { setIsLoaded, setIsLoading } = props;
useEffect(() => {
setIsLoaded(true);
setIsLoading(false);
}, []);
return <TfaAuthForm {...props} />;
};
const ComponentWrapper = inject(({ settingsStore, confirm }) => ({
setIsLoaded: confirm.setIsLoaded,
setIsLoading: confirm.setIsLoading,
defaultPage: settingsStore.defaultPage,
}))(withTranslation(["Confirm", "Common"])(observer(TfaAuthFormWrapper)));
export const Component = () => {
return (
<ConfirmRoute>
<ComponentWrapper />
</ConfirmRoute>
);
};

View File

@ -1,196 +0,0 @@
// (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, { useEffect, useState } from "react";
import { observer, inject } from "mobx-react";
import { useNavigate } from "react-router-dom";
import { Loader } from "@docspace/shared/components/loader";
import axios from "axios";
import { combineUrl } from "@docspace/shared/utils/combineUrl";
import ConfirmWrapper from "./ConfirmWrapper";
import { getUserByEmail } from "@docspace/shared/api/people";
let loadTimeout = null;
export default function withLoader(WrappedComponent) {
const withLoader = (props) => {
const {
tReady,
isLoading,
linkData,
passwordSettings,
getSettings,
getPortalPasswordSettings,
getAuthProviders,
getCapabilities,
} = props;
const [inLoad, setInLoad] = useState(false);
const type = linkData ? linkData.type : null;
const confirmHeader = linkData ? linkData.confirmHeader : null;
const email = linkData ? linkData.email : null;
const navigate = useNavigate();
const fetch = async () => {
if (type === "EmpInvite" && email) {
try {
await getUserByEmail(email, confirmHeader);
const loginData = window.btoa(
JSON.stringify({
type: "invitation",
email: email,
}),
);
window.location.href = combineUrl(
window.ClientConfig?.proxy?.url,
"/login",
`?loginData=${loginData}`,
);
return;
} catch (e) {}
}
try {
await getPortalPasswordSettings(confirmHeader);
} catch (error) {
let errorMessage = "";
if (typeof error === "object") {
errorMessage =
error?.response?.data?.error?.message ||
error?.statusText ||
error?.message ||
"";
} else {
errorMessage = error;
}
console.error(errorMessage);
navigate(
combineUrl(
window.ClientConfig?.proxy?.url,
`/login/error?message=${errorMessage}`,
),
);
}
};
useEffect(() => {
if (
(type === "PasswordChange" ||
type === "LinkInvite" ||
type === "Activation" ||
type === "EmpInvite") &&
!passwordSettings
) {
fetch();
}
}, [passwordSettings]);
useEffect(() => {
if (type === "LinkInvite" || type === "EmpInvite") {
axios.all([getAuthProviders(), getCapabilities()]).catch((error) => {
let errorMessage = "";
if (typeof error === "object") {
errorMessage =
error?.response?.data?.error?.message ||
error?.statusText ||
error?.message ||
"";
} else {
errorMessage = error;
}
console.error(errorMessage);
navigate(
combineUrl(
window.ClientConfig?.proxy?.url,
`/login/error?message=${errorMessage}`,
),
);
});
}
}, []);
const isLoaded =
type === "TfaActivation" || type === "TfaAuth"
? props.isLoaded
: type === "PasswordChange" ||
type === "LinkInvite" ||
type === "Activation" ||
type === "EmpInvite"
? !!passwordSettings
: true;
const cleanTimer = () => {
loadTimeout && clearTimeout(loadTimeout);
loadTimeout = null;
};
useEffect(() => {
if (isLoading) {
cleanTimer();
loadTimeout = setTimeout(() => {
setInLoad(true);
}, 500);
} else {
cleanTimer();
setInLoad(false);
}
return () => {
cleanTimer();
};
}, [isLoading]);
return !isLoaded || !tReady ? (
<Loader className="pageLoader" type="rombs" size="40px" />
) : (
<ConfirmWrapper>
<WrappedComponent {...props} />
</ConfirmWrapper>
);
};
return inject(({ authStore, settingsStore, confirm }) => {
const { isLoaded, isLoading } = confirm;
const { passwordSettings, getSettings, getPortalPasswordSettings } =
settingsStore;
const { getAuthProviders, getCapabilities } = authStore;
return {
isLoaded,
isLoading,
getSettings,
passwordSettings,
getPortalPasswordSettings,
getAuthProviders,
getCapabilities,
};
})(observer(withLoader));
}