Login: delete old files
This commit is contained in:
parent
9c986d3bc7
commit
a3af4a49cc
@ -1,50 +0,0 @@
|
||||
import React from "react";
|
||||
import Login from "./components/Login";
|
||||
import { Routes, Route } from "react-router-dom";
|
||||
import InvalidRoute from "./components/Invalid";
|
||||
import CodeLogin from "./components/CodeLogin";
|
||||
import initLoginStore from "../store";
|
||||
import { Provider as MobxProvider } from "mobx-react";
|
||||
import SimpleNav from "../client/components/sub-components/SimpleNav";
|
||||
import { WRONG_PORTAL_NAME_URL } from "@docspace/shared/constants";
|
||||
|
||||
interface ILoginProps extends IInitialState {
|
||||
isDesktopEditor?: boolean;
|
||||
theme: IUserTheme;
|
||||
setTheme: (theme: IUserTheme) => void;
|
||||
}
|
||||
|
||||
const App: React.FC<ILoginProps> = (props) => {
|
||||
const loginStore = initLoginStore(props?.currentColorScheme || {});
|
||||
|
||||
React.useEffect(() => {
|
||||
if (window && props.error) {
|
||||
const { status, standalone, message } = props.error;
|
||||
|
||||
if (status === 404 && !standalone) {
|
||||
const url = new URL(WRONG_PORTAL_NAME_URL);
|
||||
url.searchParams.append("url", window.location.hostname);
|
||||
window.location.replace(url);
|
||||
}
|
||||
|
||||
throw new Error(message);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<MobxProvider {...loginStore}>
|
||||
<SimpleNav {...props} />
|
||||
<Routes>
|
||||
<Route
|
||||
path="/login/consent"
|
||||
element={<Login isConsent={props.isAuth} {...props} />}
|
||||
/>
|
||||
<Route path="/login/error" element={<InvalidRoute {...props} />} />
|
||||
{/*<Route path="/login/code" element={<CodeLogin {...props} />} />*/}
|
||||
<Route path="/login" element={<Login {...props} />} />
|
||||
</Routes>
|
||||
</MobxProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
@ -1,360 +0,0 @@
|
||||
import React, { useState, useCallback, useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { ButtonsWrapper, LoginFormWrapper, LoginContent } from "./StyledLogin";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { SocialButton } from "@docspace/shared/components/social-button";
|
||||
import {
|
||||
getProviderTranslation,
|
||||
getOAuthToken,
|
||||
getLoginLink,
|
||||
} from "@docspace/shared/utils/common";
|
||||
import { checkIsSSR } from "@docspace/shared/utils";
|
||||
import { PROVIDERS_DATA } from "@docspace/shared/constants";
|
||||
import { Link } from "@docspace/shared/components/link";
|
||||
import { Toast } from "@docspace/shared/components/toast";
|
||||
import LoginForm from "./sub-components/LoginForm";
|
||||
import RecoverAccessModalDialog from "@docspace/shared/components/recover-access-modal-dialog/RecoverAccessModalDialog";
|
||||
import MoreLoginModal from "@docspace/shared/components/more-login-modal";
|
||||
import { FormWrapper } from "@docspace/shared/components/form-wrapper";
|
||||
import Register from "./sub-components/register-container";
|
||||
import { ColorTheme, ThemeId } from "@docspace/shared/components/color-theme";
|
||||
import SSOIcon from "PUBLIC_DIR/images/sso.react.svg";
|
||||
import { Dark, Base } from "@docspace/shared/themes";
|
||||
import { useMounted } from "../helpers/useMounted";
|
||||
import { getBgPattern, frameCallCommand } from "@docspace/shared/utils/common";
|
||||
import useIsomorphicLayoutEffect from "../hooks/useIsomorphicLayoutEffect";
|
||||
import { getLogoFromPath, getSystemTheme } from "@docspace/shared/utils";
|
||||
import { TenantStatus } from "@docspace/shared/enums";
|
||||
import Consent from "./sub-components/Consent";
|
||||
import { IClientProps, IScope } from "@docspace/common/utils/oauth/interfaces";
|
||||
|
||||
const themes = {
|
||||
Dark: Dark,
|
||||
Base: Base,
|
||||
};
|
||||
|
||||
interface ILoginProps extends IInitialState {
|
||||
isDesktopEditor?: boolean;
|
||||
theme: IUserTheme;
|
||||
setTheme: (theme: IUserTheme) => void;
|
||||
isBaseTheme: boolean;
|
||||
isConsent?: boolean;
|
||||
}
|
||||
|
||||
const Login: React.FC<ILoginProps> = ({
|
||||
portalSettings,
|
||||
providers,
|
||||
capabilities,
|
||||
isDesktopEditor,
|
||||
match,
|
||||
currentColorScheme,
|
||||
theme,
|
||||
setTheme,
|
||||
logoUrls,
|
||||
isBaseTheme,
|
||||
oauth,
|
||||
isConsent,
|
||||
}) => {
|
||||
const isOAuthPage = !!oauth?.client.name;
|
||||
|
||||
const isRestoringPortal =
|
||||
portalSettings?.tenantStatus === TenantStatus.PortalRestore;
|
||||
|
||||
useEffect(() => {
|
||||
isRestoringPortal && window.location.replace("/preparation-portal");
|
||||
}, []);
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [moreAuthVisible, setMoreAuthVisible] = useState(false);
|
||||
const [recoverDialogVisible, setRecoverDialogVisible] = useState(false);
|
||||
const [isConsentPage, setIsConsentPage] = useState(
|
||||
isConsent || oauth?.isConsent
|
||||
);
|
||||
const [scopes, setScopes] = useState(oauth?.scopes || ([] as IScope[]));
|
||||
const [oauthClient, setOAuthClient] = useState(
|
||||
oauth?.client || ({} as IClientProps)
|
||||
);
|
||||
const [self, setSelf] = useState(oauth?.self || ({} as ISelf));
|
||||
const [hashSettings, setHashSettings] = useState<null | PasswordHashType>(
|
||||
null
|
||||
);
|
||||
|
||||
const {
|
||||
enabledJoin,
|
||||
greetingSettings,
|
||||
enableAdmMess,
|
||||
cookieSettingsEnabled,
|
||||
} = portalSettings || {
|
||||
enabledJoin: false,
|
||||
greetingSettings: false,
|
||||
enableAdmMess: false,
|
||||
cookieSettingsEnabled: false,
|
||||
};
|
||||
|
||||
const ssoLabel = capabilities?.ssoLabel || "";
|
||||
const ssoUrl = capabilities?.ssoUrl || "";
|
||||
const { t } = useTranslation(["Login", "Common"]);
|
||||
const mounted = useMounted();
|
||||
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
const systemTheme = getSystemTheme();
|
||||
const theme = themes[systemTheme];
|
||||
setTheme(theme);
|
||||
frameCallCommand("setIsLoaded");
|
||||
}, []);
|
||||
|
||||
const ssoExists = () => {
|
||||
if (ssoUrl) return true;
|
||||
else return false;
|
||||
};
|
||||
|
||||
const ssoButton = () => {
|
||||
const onClick = () => (window.location.href = ssoUrl);
|
||||
return (
|
||||
<div className="buttonWrapper">
|
||||
<SocialButton
|
||||
IconComponent={SSOIcon}
|
||||
className="socialButton"
|
||||
label={ssoLabel || getProviderTranslation("sso", t)}
|
||||
onClick={onClick}
|
||||
isDisabled={isLoading}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
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 onSocialButtonClick = useCallback(
|
||||
async (e: HTMLElementEvent<HTMLButtonElement | HTMLElement>) => {
|
||||
const { target } = e;
|
||||
let targetElement = target;
|
||||
|
||||
if (
|
||||
!(targetElement instanceof HTMLButtonElement) &&
|
||||
target.parentElement
|
||||
) {
|
||||
targetElement = target.parentElement;
|
||||
}
|
||||
const providerName = targetElement.dataset.providername;
|
||||
let url = targetElement.dataset.url || "";
|
||||
|
||||
try {
|
||||
//Lifehack for Twitter
|
||||
if (providerName == "twitter") {
|
||||
url += "authCallback";
|
||||
}
|
||||
|
||||
const tokenGetterWin = isDesktopEditor
|
||||
? (window.location.href = url)
|
||||
: window.open(
|
||||
url,
|
||||
"login",
|
||||
"width=800,height=500,status=no,toolbar=no,menubar=no,resizable=yes,scrollbars=no"
|
||||
);
|
||||
|
||||
const code: string = await getOAuthToken(tokenGetterWin);
|
||||
|
||||
const token = window.btoa(
|
||||
JSON.stringify({
|
||||
auth: providerName,
|
||||
mode: "popup",
|
||||
callback: "authCallback",
|
||||
})
|
||||
);
|
||||
|
||||
if (tokenGetterWin && typeof tokenGetterWin !== "string")
|
||||
tokenGetterWin.location.href = getLoginLink(token, code);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const providerButtons = () => {
|
||||
const providerButtons =
|
||||
providers &&
|
||||
providers.map((item, index) => {
|
||||
if (!PROVIDERS_DATA[item.provider]) return;
|
||||
if (index > 1) return;
|
||||
|
||||
const { icon, label, iconOptions, className } =
|
||||
PROVIDERS_DATA[item.provider];
|
||||
|
||||
return (
|
||||
<div className="buttonWrapper" key={`${item.provider}ProviderItem`}>
|
||||
<SocialButton
|
||||
iconName={icon}
|
||||
label={getProviderTranslation(label, t)}
|
||||
className={`socialButton ${className ? className : ""}`}
|
||||
$iconOptions={iconOptions}
|
||||
data-url={item.url}
|
||||
data-providername={item.provider}
|
||||
onClick={onSocialButtonClick}
|
||||
isDisabled={isLoading}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
return providerButtons;
|
||||
};
|
||||
|
||||
const moreAuthOpen = () => {
|
||||
setMoreAuthVisible(true);
|
||||
};
|
||||
|
||||
const moreAuthClose = () => {
|
||||
setMoreAuthVisible(false);
|
||||
};
|
||||
|
||||
const openRecoverDialog = () => {
|
||||
setRecoverDialogVisible(true);
|
||||
};
|
||||
|
||||
const closeRecoverDialog = () => {
|
||||
setRecoverDialogVisible(false);
|
||||
};
|
||||
|
||||
const bgPattern = getBgPattern(currentColorScheme?.id);
|
||||
|
||||
const logo = logoUrls && Object.values(logoUrls)[1];
|
||||
const logoUrl = !logo
|
||||
? undefined
|
||||
: !theme?.isBase
|
||||
? getLogoFromPath(logo.path.dark)
|
||||
: getLogoFromPath(logo.path.light);
|
||||
|
||||
if (!mounted) return <></>;
|
||||
if (isRestoringPortal) return <></>;
|
||||
|
||||
return (
|
||||
<LoginFormWrapper
|
||||
id="login-page"
|
||||
enabledJoin={enabledJoin}
|
||||
isDesktop={isDesktopEditor}
|
||||
bgPattern={bgPattern}
|
||||
>
|
||||
<div className="bg-cover"></div>
|
||||
<LoginContent enabledJoin={enabledJoin}>
|
||||
<ColorTheme themeId={ThemeId.LinkForgotPassword}>
|
||||
<img src={logoUrl} className="logo-wrapper" />
|
||||
<Text
|
||||
fontSize="23px"
|
||||
fontWeight={700}
|
||||
textAlign="center"
|
||||
className="greeting-title"
|
||||
>
|
||||
{greetingSettings}
|
||||
</Text>
|
||||
{isConsentPage && isOAuthPage ? (
|
||||
<Consent
|
||||
oauth={{ ...oauth, scopes, client: oauthClient, self }}
|
||||
theme={theme}
|
||||
hashSettings={portalSettings?.passwordHash || hashSettings}
|
||||
setHashSettings={setHashSettings}
|
||||
setIsConsentScreen={setIsConsentPage}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<FormWrapper id="login-form" theme={theme}>
|
||||
{ssoExists() && !isOAuthPage && (
|
||||
<ButtonsWrapper>{ssoButton()}</ButtonsWrapper>
|
||||
)}
|
||||
{oauthDataExists() && !isOAuthPage && (
|
||||
<>
|
||||
<ButtonsWrapper>{providerButtons()}</ButtonsWrapper>
|
||||
{providers && providers.length > 2 && (
|
||||
<Link
|
||||
isHovered
|
||||
type="action"
|
||||
fontSize="13px"
|
||||
fontWeight="600"
|
||||
color={currentColorScheme?.main?.accent}
|
||||
className="more-label"
|
||||
onClick={moreAuthOpen}
|
||||
>
|
||||
{t("Common:ShowMore")}
|
||||
</Link>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{(oauthDataExists() || ssoExists()) && !isOAuthPage && (
|
||||
<div className="line">
|
||||
<Text className="or-label">{t("Or")}</Text>
|
||||
</div>
|
||||
)}
|
||||
<LoginForm
|
||||
isBaseTheme={isBaseTheme}
|
||||
recaptchaPublicKey={portalSettings?.recaptchaPublicKey}
|
||||
isDesktop={!!isDesktopEditor}
|
||||
isLoading={isLoading}
|
||||
hashSettings={portalSettings?.passwordHash || hashSettings}
|
||||
setIsLoading={setIsLoading}
|
||||
openRecoverDialog={openRecoverDialog}
|
||||
match={match}
|
||||
enableAdmMess={enableAdmMess}
|
||||
cookieSettingsEnabled={cookieSettingsEnabled}
|
||||
isOAuthPage={isOAuthPage}
|
||||
oauth={oauth}
|
||||
setIsConsentPage={setIsConsentPage}
|
||||
setScopes={setScopes}
|
||||
setOAuthClient={setOAuthClient}
|
||||
setSelf={setSelf}
|
||||
/>
|
||||
</FormWrapper>
|
||||
<Toast />
|
||||
<MoreLoginModal
|
||||
visible={moreAuthVisible}
|
||||
onClose={moreAuthClose}
|
||||
providers={providers}
|
||||
onSocialLoginClick={onSocialButtonClick}
|
||||
ssoLabel={ssoLabel}
|
||||
ssoUrl={ssoUrl}
|
||||
t={t}
|
||||
/>
|
||||
<RecoverAccessModalDialog
|
||||
visible={recoverDialogVisible}
|
||||
onClose={closeRecoverDialog}
|
||||
textBody={t("RecoverTextBody")}
|
||||
emailPlaceholderText={t("RecoverContactEmailPlaceholder")}
|
||||
id="recover-access-modal"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</ColorTheme>
|
||||
</LoginContent>
|
||||
|
||||
{!checkIsSSR() && !oauth?.self && enabledJoin && (
|
||||
<Register
|
||||
id="login_register"
|
||||
enabledJoin={enabledJoin}
|
||||
currentColorScheme={currentColorScheme}
|
||||
trustedDomains={portalSettings?.trustedDomains}
|
||||
trustedDomainsType={portalSettings?.trustedDomainsType}
|
||||
/>
|
||||
)}
|
||||
</LoginFormWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ loginStore }) => {
|
||||
return {
|
||||
theme: loginStore.theme,
|
||||
setTheme: loginStore.setTheme,
|
||||
isBaseTheme: loginStore.theme.isBase,
|
||||
};
|
||||
})(observer(Login));
|
@ -1,527 +0,0 @@
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { FieldContainer } from "@docspace/shared/components/field-container";
|
||||
import { EmailInput } from "@docspace/shared/components/email-input";
|
||||
import { PasswordInput } from "@docspace/shared/components/password-input";
|
||||
import { Checkbox } from "@docspace/shared/components/checkbox";
|
||||
import { HelpButton } from "@docspace/shared/components/help-button";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { Link, LinkType } from "@docspace/shared/components/link";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ForgotPasswordModalDialog from "./forgot-password-modal-dialog";
|
||||
import { Button, ButtonSize } from "@docspace/shared/components/button";
|
||||
import { createPasswordHash } from "@docspace/shared/utils/common";
|
||||
import { checkIsSSR } from "@docspace/shared/utils";
|
||||
import { checkPwd } from "@docspace/shared/utils/desktop";
|
||||
import { login } from "@docspace/shared/utils/loginUtils";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
import { thirdPartyLogin } from "@docspace/shared/api/user";
|
||||
import { setWithCredentialsStatus } from "@docspace/shared/api/client";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
import ReCAPTCHA from "react-google-recaptcha";
|
||||
import { OAuthLinksContainer, StyledCaptcha } from "../StyledLogin";
|
||||
import OAuthClientInfo from "./oauth-client-info";
|
||||
import SelectUser from "./SelectUser";
|
||||
import { getClient, getScopeList } from "@docspace/shared/api/oauth";
|
||||
import { getUser } from "@docspace/shared/api/people";
|
||||
import { onOAuthLogin } from "@docspace/shared/api/oauth";
|
||||
import { IClientProps, IScope } from "@docspace/shared/utils/oauth/interfaces";
|
||||
import { setCookie } from "@docspace/shared/utils/cookie";
|
||||
import { InputSize } from "@docspace/shared/components/text-input";
|
||||
|
||||
interface ILoginFormProps {
|
||||
isLoading: boolean;
|
||||
setIsLoading: (isLoading: boolean) => void;
|
||||
hashSettings: PasswordHashType | null;
|
||||
isDesktop: boolean;
|
||||
match: MatchType;
|
||||
openRecoverDialog: () => void;
|
||||
enableAdmMess: boolean;
|
||||
recaptchaPublicKey: CaptchaPublicKeyType;
|
||||
isBaseTheme: boolean;
|
||||
oauth?: IOAuthState;
|
||||
isOAuthPage?: boolean;
|
||||
setIsConsentPage?: (val: boolean) => void;
|
||||
setScopes: (val: IScope[]) => void;
|
||||
setOAuthClient: (val: IClientProps) => void;
|
||||
setSelf: (val: ISelf) => void;
|
||||
}
|
||||
|
||||
const settings = {
|
||||
minLength: 6,
|
||||
upperCase: false,
|
||||
digits: false,
|
||||
specSymbols: false,
|
||||
};
|
||||
|
||||
const LoginForm: React.FC<ILoginFormProps> = ({
|
||||
isLoading,
|
||||
hashSettings,
|
||||
isDesktop,
|
||||
match,
|
||||
setIsLoading,
|
||||
openRecoverDialog,
|
||||
enableAdmMess,
|
||||
cookieSettingsEnabled,
|
||||
recaptchaPublicKey,
|
||||
isBaseTheme,
|
||||
oauth,
|
||||
isOAuthPage,
|
||||
setIsConsentPage,
|
||||
setScopes,
|
||||
setOAuthClient,
|
||||
setSelf,
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const captchaRef = useRef(null);
|
||||
|
||||
const [isEmailErrorShow, setIsEmailErrorShow] = useState(false);
|
||||
const [errorText, setErrorText] = useState("");
|
||||
const [identifier, setIdentifier] = useState("");
|
||||
const [passwordValid, setPasswordValid] = useState(true);
|
||||
const [identifierValid, setIdentifierValid] = useState(true);
|
||||
const [password, setPassword] = useState("");
|
||||
const [isDisabled, setIsDisabled] = useState(false);
|
||||
const [isChecked, setIsChecked] = useState(false);
|
||||
const [isDialogVisible, setIsDialogVisible] = useState(false);
|
||||
const [isCaptcha, setIsCaptcha] = useState(false);
|
||||
const [isWithoutPasswordLogin, setIsWithoutPasswordLogin] =
|
||||
useState(IS_ROOMS_MODE);
|
||||
|
||||
const [isCaptchaSuccessful, setIsCaptchaSuccess] = useState(false);
|
||||
const [isCaptchaError, setIsCaptchaError] = useState(false);
|
||||
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const { t, ready } = useTranslation(["Login", "Common", "Consent"]);
|
||||
|
||||
const { message, confirmedEmail, authError } = match || {
|
||||
message: "",
|
||||
confirmedEmail: "",
|
||||
authError: "",
|
||||
};
|
||||
|
||||
const authCallback = (profile: string) => {
|
||||
localStorage.removeItem("profile");
|
||||
localStorage.removeItem("code");
|
||||
|
||||
thirdPartyLogin(profile)
|
||||
.then((response) => {
|
||||
if (!(response || response.token || response.confirmUrl))
|
||||
throw new Error("Empty API response");
|
||||
|
||||
setWithCredentialsStatus(true);
|
||||
|
||||
if (response.confirmUrl) {
|
||||
return window.location.replace(response.confirmUrl);
|
||||
}
|
||||
|
||||
const redirectPath = sessionStorage.getItem("referenceUrl");
|
||||
|
||||
if (redirectPath) {
|
||||
sessionStorage.removeItem("referenceUrl");
|
||||
window.location.href = redirectPath;
|
||||
} else {
|
||||
window.location.replace("/");
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
toastr.error(
|
||||
t("Common:ProviderNotConnected"),
|
||||
t("Common:ProviderLoginError")
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const profile = localStorage.getItem("profile");
|
||||
if (!profile) return;
|
||||
|
||||
authCallback(profile);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
message && setErrorText(message);
|
||||
confirmedEmail && setIdentifier(confirmedEmail);
|
||||
|
||||
const messageEmailConfirmed = t("MessageEmailConfirmed");
|
||||
const messageAuthorize = t("MessageAuthorize");
|
||||
|
||||
const text = `${messageEmailConfirmed} ${messageAuthorize}`;
|
||||
|
||||
confirmedEmail && ready && toastr.success(text);
|
||||
authError && ready && toastr.error(t("Common:ProviderLoginError"));
|
||||
|
||||
focusInput();
|
||||
|
||||
window.authCallback = authCallback;
|
||||
}, [message, confirmedEmail]);
|
||||
|
||||
const onChangeLogin = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
//console.log("onChangeLogin", e.target.value);
|
||||
setIdentifier(e.target.value);
|
||||
if (!IS_ROOMS_MODE) setIsEmailErrorShow(false);
|
||||
onClearErrors();
|
||||
};
|
||||
|
||||
const onClearErrors = () => {
|
||||
if (IS_ROOMS_MODE) {
|
||||
!identifierValid && setIdentifierValid(true);
|
||||
errorText && setErrorText("");
|
||||
setIsEmailErrorShow(false);
|
||||
} else {
|
||||
!passwordValid && setPasswordValid(true);
|
||||
}
|
||||
};
|
||||
|
||||
const onSubmit = () => {
|
||||
//errorText && setErrorText("");
|
||||
let captchaToken = "";
|
||||
|
||||
if (recaptchaPublicKey && isCaptcha) {
|
||||
if (!isCaptchaSuccessful) {
|
||||
setIsCaptchaError(true);
|
||||
return;
|
||||
}
|
||||
|
||||
captchaToken = captchaRef.current.getValue();
|
||||
}
|
||||
|
||||
let hasError = false;
|
||||
|
||||
const user = identifier.trim();
|
||||
|
||||
if (!user) {
|
||||
hasError = true;
|
||||
setIdentifierValid(false);
|
||||
setIsEmailErrorShow(true);
|
||||
}
|
||||
|
||||
if (IS_ROOMS_MODE && identifierValid) {
|
||||
window.location.replace("/login/code"); //TODO: confirm link?
|
||||
return;
|
||||
}
|
||||
|
||||
const pass = password.trim();
|
||||
|
||||
if (!pass) {
|
||||
hasError = true;
|
||||
setPasswordValid(false);
|
||||
}
|
||||
|
||||
if (!identifierValid) hasError = true;
|
||||
|
||||
if (hasError) return;
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
const hash = createPasswordHash(pass, hashSettings);
|
||||
|
||||
isDesktop && checkPwd();
|
||||
const session = !isChecked;
|
||||
|
||||
login(user, hash, session, captchaToken)
|
||||
.then((res: string | object) => {
|
||||
if (isOAuthPage) {
|
||||
const requests = [];
|
||||
|
||||
setCookie("client_id", oauth?.clientId || "");
|
||||
|
||||
requests.push(getClient(oauth?.clientId || ""));
|
||||
requests.push(getScopeList());
|
||||
requests.push(getUser());
|
||||
requests.push(onOAuthLogin());
|
||||
|
||||
Promise.all(requests).then(([client, scopes, self]) => {
|
||||
setOAuthClient(client);
|
||||
setScopes(scopes);
|
||||
setSelf(self);
|
||||
setIsConsentPage && setIsConsentPage(true);
|
||||
setIsLoading(false);
|
||||
});
|
||||
} else {
|
||||
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("/"); //TODO: save { user, hash } for tfa
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
let errorMessage = "";
|
||||
if (typeof error === "object") {
|
||||
errorMessage =
|
||||
error?.response?.data?.error?.message ||
|
||||
error?.statusText ||
|
||||
error?.message ||
|
||||
"";
|
||||
} else {
|
||||
errorMessage = error;
|
||||
}
|
||||
|
||||
if (recaptchaPublicKey && error?.response?.status === 403) {
|
||||
setIsCaptcha(true);
|
||||
}
|
||||
|
||||
if (isCaptcha) {
|
||||
captchaRef.current.reset();
|
||||
}
|
||||
|
||||
setIsEmailErrorShow(true);
|
||||
setErrorText(errorMessage);
|
||||
setPasswordValid(!errorMessage);
|
||||
setIsLoading(false);
|
||||
focusInput();
|
||||
});
|
||||
};
|
||||
|
||||
const onLoginWithPasswordClick = () => {
|
||||
setIsWithoutPasswordLogin(false);
|
||||
};
|
||||
|
||||
const onBlurEmail = () => {
|
||||
!identifierValid && setIsEmailErrorShow(true);
|
||||
};
|
||||
|
||||
const onValidateEmail = (res: IEmailValid) => {
|
||||
setIdentifierValid(res.isValid);
|
||||
setErrorText(res.errors[0]);
|
||||
};
|
||||
|
||||
const focusInput = () => {
|
||||
if (inputRef && inputRef.current) {
|
||||
inputRef.current.focus();
|
||||
}
|
||||
};
|
||||
|
||||
const onChangePassword = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setPassword(e.target.value);
|
||||
onClearErrors();
|
||||
};
|
||||
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.key === "Enter") {
|
||||
onClearErrors();
|
||||
!isDisabled && onSubmit();
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
const onChangeCheckbox = () => setIsChecked(!isChecked);
|
||||
|
||||
const onClick = () => {
|
||||
setIsDialogVisible(true);
|
||||
setIsDisabled(true);
|
||||
};
|
||||
|
||||
const onDialogClose = () => {
|
||||
setIsDialogVisible(false);
|
||||
setIsDisabled(false);
|
||||
setIsLoading(false);
|
||||
};
|
||||
|
||||
const onSuccessfullyComplete = () => {
|
||||
setIsCaptchaSuccess(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<form className="auth-form-container">
|
||||
{oauth?.client && isOAuthPage && (
|
||||
<OAuthClientInfo
|
||||
t={t}
|
||||
name={oauth.client.name}
|
||||
logo={oauth.client.logo}
|
||||
websiteUrl={oauth.client.websiteUrl}
|
||||
/>
|
||||
)}
|
||||
<>
|
||||
<FieldContainer
|
||||
isVertical
|
||||
labelVisible={false}
|
||||
hasError={isEmailErrorShow}
|
||||
errorMessage={
|
||||
errorText ? t(`Common:${errorText}`) : t("Common:RequiredField")
|
||||
} //TODO: Add wrong login server error
|
||||
>
|
||||
<EmailInput
|
||||
id="login_username"
|
||||
name="login"
|
||||
type="email"
|
||||
hasError={isEmailErrorShow}
|
||||
value={identifier}
|
||||
placeholder={t("RegistrationEmailWatermark")}
|
||||
size={InputSize.large}
|
||||
scale
|
||||
isAutoFocussed
|
||||
tabIndex={1}
|
||||
isDisabled={isLoading}
|
||||
autoComplete="username"
|
||||
onChange={onChangeLogin}
|
||||
onBlur={onBlurEmail}
|
||||
onValidateInput={onValidateEmail}
|
||||
forwardedRef={inputRef}
|
||||
/>
|
||||
</FieldContainer>
|
||||
{(!IS_ROOMS_MODE || !isWithoutPasswordLogin) && (
|
||||
<>
|
||||
<FieldContainer
|
||||
isVertical
|
||||
labelVisible={false}
|
||||
hasError={!passwordValid}
|
||||
errorMessage={!password.trim() ? t("Common:RequiredField") : ""} //TODO: Add wrong password server error
|
||||
>
|
||||
<PasswordInput
|
||||
className="password-input"
|
||||
simpleView
|
||||
passwordSettings={settings}
|
||||
id="login_password"
|
||||
inputName="password"
|
||||
placeholder={t("Common:Password")}
|
||||
type="password"
|
||||
hasError={!passwordValid}
|
||||
inputValue={password}
|
||||
size={InputSize.large}
|
||||
scale
|
||||
tabIndex={1}
|
||||
isDisabled={isLoading}
|
||||
autoComplete="current-password"
|
||||
onChange={onChangePassword}
|
||||
onKeyDown={onKeyDown}
|
||||
/>
|
||||
</FieldContainer>
|
||||
|
||||
<div className="login-forgot-wrapper">
|
||||
<div className="login-checkbox-wrapper">
|
||||
<div className="remember-wrapper">
|
||||
{!cookieSettingsEnabled && (
|
||||
<Checkbox
|
||||
id="login_remember"
|
||||
className="login-checkbox"
|
||||
isChecked={isChecked}
|
||||
onChange={onChangeCheckbox}
|
||||
label={t("Common:Remember")}
|
||||
helpButton={
|
||||
!checkIsSSR() && (
|
||||
<HelpButton
|
||||
id="login_remember-hint"
|
||||
className="help-button"
|
||||
offsetRight={0}
|
||||
helpButtonHeaderContent={t("CookieSettingsTitle")}
|
||||
tooltipContent={
|
||||
<Text fontSize="12px">{t("RememberHelper")}</Text>
|
||||
}
|
||||
tooltipMaxWidth={isMobileOnly ? "240px" : "340px"}
|
||||
/>
|
||||
)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Link
|
||||
fontSize="13px"
|
||||
className="login-link"
|
||||
type="page"
|
||||
isHovered={false}
|
||||
onClick={onClick}
|
||||
id="login_forgot-password-link"
|
||||
>
|
||||
{t("ForgotPassword")}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isDialogVisible && (
|
||||
<ForgotPasswordModalDialog
|
||||
isVisible={isDialogVisible}
|
||||
userEmail={identifier}
|
||||
onDialogClose={onDialogClose}
|
||||
/>
|
||||
)}
|
||||
{recaptchaPublicKey && isCaptcha && (
|
||||
<StyledCaptcha isCaptchaError={isCaptchaError}>
|
||||
<div className="captcha-wrapper">
|
||||
<ReCAPTCHA
|
||||
sitekey={recaptchaPublicKey}
|
||||
ref={captchaRef}
|
||||
theme={isBaseTheme ? "light" : "dark"}
|
||||
onChange={onSuccessfullyComplete}
|
||||
/>
|
||||
</div>
|
||||
{isCaptchaError && (
|
||||
<Text>{t("Errors:LoginWithBruteForceCaptcha")}</Text>
|
||||
)}
|
||||
</StyledCaptcha>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
<Button
|
||||
id="login_submit"
|
||||
className="login-button"
|
||||
primary
|
||||
size={ButtonSize.medium}
|
||||
scale
|
||||
label={
|
||||
isLoading ? t("Common:LoadingProcessing") : t("Common:LoginButton")
|
||||
}
|
||||
tabIndex={1}
|
||||
isDisabled={isLoading}
|
||||
isLoading={isLoading}
|
||||
onClick={onSubmit}
|
||||
/>
|
||||
</>
|
||||
{/*Uncomment when add api*/}
|
||||
{(!IS_ROOMS_MODE || !isWithoutPasswordLogin) && !isOAuthPage && (
|
||||
<div className="login-or-access">
|
||||
{/*<Link
|
||||
fontWeight="600"
|
||||
fontSize="13px"
|
||||
type={LinkType.action}
|
||||
isHovered
|
||||
onClick={onLoginWithCodeClick}
|
||||
>
|
||||
{t("SignInWithCode")}
|
||||
</Link>*/}
|
||||
{enableAdmMess && (
|
||||
<>
|
||||
<Text className="login-or-access-text">{t("Or")}</Text>
|
||||
<Link
|
||||
id="login_recover-link"
|
||||
fontWeight="600"
|
||||
fontSize="13px"
|
||||
type={LinkType.action}
|
||||
isHovered
|
||||
className="login-link recover-link"
|
||||
onClick={openRecoverDialog}
|
||||
>
|
||||
{t("RecoverAccess")}
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{IS_ROOMS_MODE && isWithoutPasswordLogin && !isOAuthPage && (
|
||||
<div className="login-link">
|
||||
<Link
|
||||
fontWeight="600"
|
||||
fontSize="13px"
|
||||
type={LinkType.action}
|
||||
isHovered
|
||||
onClick={onLoginWithPasswordClick}
|
||||
>
|
||||
{t("SignInWithPassword")}
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoginForm;
|
@ -37,7 +37,7 @@ import React, {
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ReCAPTCHA from "react-google-recaptcha";
|
||||
import { useTheme } from "styled-components";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { useSearchParams, useRouter } from "next/navigation";
|
||||
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { Button, ButtonSize } from "@docspace/shared/components/button";
|
||||
@ -60,7 +60,6 @@ import { StyledCaptcha } from "./LoginForm.styled";
|
||||
import { LoginDispatchContext, LoginValueContext } from "../Login";
|
||||
import OAuthClientInfo from "../ConsentInfo";
|
||||
import api from "@docspace/shared/api";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
const LoginForm = ({
|
||||
hashSettings,
|
||||
@ -298,6 +297,7 @@ const LoginForm = ({
|
||||
isCaptchaSuccessful,
|
||||
clientId,
|
||||
referenceUrl,
|
||||
router,
|
||||
]);
|
||||
|
||||
const onBlurEmail = () => {
|
||||
|
@ -1,39 +0,0 @@
|
||||
import i18next from "i18next";
|
||||
|
||||
import { translations } from "SRC_DIR/autoGeneratedTranslations";
|
||||
|
||||
const fallbackLng = "en";
|
||||
|
||||
const resources: {
|
||||
[key: string]: { [key: string]: {} };
|
||||
} = {};
|
||||
|
||||
translations.forEach((lngCol: Map<string, {}>, key: string) => {
|
||||
resources[key] = {};
|
||||
lngCol.forEach((data, ns: string) => {
|
||||
if (resources[key]) {
|
||||
resources[key][ns] = data;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
i18next.init({
|
||||
fallbackLng: fallbackLng,
|
||||
load: "currentOnly",
|
||||
|
||||
saveMissing: true,
|
||||
ns: ["Login", "Errors", "Consent", "Common"],
|
||||
defaultNS: "Login",
|
||||
|
||||
resources,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
format: function (value, format) {
|
||||
if (format === "lowercase") return value.toLowerCase();
|
||||
return value;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default i18next;
|
@ -1,235 +0,0 @@
|
||||
import { getAppearanceTheme } from "@docspace/shared/api/settings";
|
||||
import express, { Response } from "express";
|
||||
import template from "./lib/template";
|
||||
import path from "path";
|
||||
import compression from "compression";
|
||||
import ws from "./lib/websocket";
|
||||
import fs from "fs";
|
||||
import logger from "morgan";
|
||||
import winston, { stream } from "./lib/logger";
|
||||
import { getAssets, getInitialState, getOAuthState } from "./lib/helpers";
|
||||
import renderApp from "./lib/helpers/render-app";
|
||||
import i18nextMiddleware from "i18next-express-middleware";
|
||||
import i18next from "./i18n";
|
||||
import cookieParser from "cookie-parser";
|
||||
|
||||
import { LANGUAGE, COOKIE_EXPIRATION_YEAR } from "@docspace/shared/constants";
|
||||
import { getLanguage } from "@docspace/shared/utils";
|
||||
import { initSSR } from "@docspace/shared/api/client";
|
||||
import { checkIsAuthenticated } from "@docspace/shared/api/user";
|
||||
import dns from "dns";
|
||||
import { xss } from "express-xss-sanitizer";
|
||||
|
||||
let port = PORT;
|
||||
|
||||
dns.setDefaultResultOrder("ipv4first");
|
||||
|
||||
const config = fs.readFileSync(path.join(__dirname, "config.json"), "utf-8");
|
||||
const parsedConfig: IParsedConfig = JSON.parse(config);
|
||||
|
||||
if (parsedConfig.PORT) {
|
||||
port = parsedConfig.PORT;
|
||||
}
|
||||
|
||||
const app = express();
|
||||
app.use(i18nextMiddleware.handle(i18next));
|
||||
app.use(compression());
|
||||
app.use(cookieParser());
|
||||
app.use(xss());
|
||||
app.use(
|
||||
"/login",
|
||||
express.static(path.resolve(path.join(__dirname, "client")), {
|
||||
// don`t delete
|
||||
// https://github.com/pillarjs/send/issues/110
|
||||
cacheControl: false,
|
||||
})
|
||||
);
|
||||
|
||||
app.use(
|
||||
logger("dev", {
|
||||
stream: stream,
|
||||
skip: function (req, res) {
|
||||
if (req.url == "/health") {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
app.get("*", async (req: ILoginRequest, res: Response, next) => {
|
||||
const { i18n, cookies, headers, query, t, url } = req;
|
||||
let initialState: IInitialState = {};
|
||||
let assets: assetsType;
|
||||
let standalone = false;
|
||||
|
||||
if (url === "/health") {
|
||||
return res.send({ status: "Healthy" });
|
||||
}
|
||||
|
||||
initSSR(headers);
|
||||
|
||||
try {
|
||||
const oauthClientId =
|
||||
(query.client_id as string) || (query.clientId as string) || "";
|
||||
|
||||
const isOAuth = query.type === "oauth2" && !!oauthClientId;
|
||||
|
||||
if (isOAuth && oauthClientId === "error") {
|
||||
res.redirect("/login/error");
|
||||
return next();
|
||||
}
|
||||
|
||||
const isAuth = await checkIsAuthenticated();
|
||||
|
||||
if (isAuth && !isOAuth && url !== "/login/error") {
|
||||
res.redirect("/");
|
||||
return next();
|
||||
}
|
||||
|
||||
initialState = await getInitialState(query, isAuth);
|
||||
const hideAuthPage = initialState?.ssoSettings?.hideAuthPage;
|
||||
const ssoUrl = initialState?.capabilities?.ssoUrl;
|
||||
|
||||
if (hideAuthPage && ssoUrl && query.skipssoredirect !== "true") {
|
||||
res.redirect(ssoUrl);
|
||||
return next();
|
||||
}
|
||||
|
||||
let isCorrectOAuth = false;
|
||||
|
||||
if (isOAuth) {
|
||||
const oauthState: IOAuthState = await getOAuthState(
|
||||
oauthClientId,
|
||||
isAuth
|
||||
);
|
||||
|
||||
const isConsent = isAuth;
|
||||
|
||||
oauthState.isConsent = !!isConsent;
|
||||
|
||||
isCorrectOAuth = !!oauthState?.client.name;
|
||||
|
||||
if (isCorrectOAuth) {
|
||||
initialState.oauth = oauthState;
|
||||
}
|
||||
}
|
||||
|
||||
if (initialState?.portalSettings?.wizardToken) {
|
||||
res.redirect("/wizard");
|
||||
return next();
|
||||
}
|
||||
|
||||
let currentLanguage: string = initialState?.portalSettings?.culture || "en";
|
||||
standalone = initialState?.portalSettings?.standalone ? true : false;
|
||||
|
||||
if (cookies && cookies[LANGUAGE]) {
|
||||
currentLanguage = cookies[LANGUAGE];
|
||||
} else {
|
||||
res.cookie(LANGUAGE, currentLanguage, {
|
||||
maxAge: COOKIE_EXPIRATION_YEAR,
|
||||
});
|
||||
}
|
||||
|
||||
currentLanguage = getLanguage(currentLanguage);
|
||||
|
||||
if (i18n) await i18n.changeLanguage(currentLanguage);
|
||||
|
||||
let initialI18nStore: {
|
||||
[key: string]: { [key: string]: {} };
|
||||
} = {};
|
||||
|
||||
if (i18n && i18n?.services?.resourceStore?.data) {
|
||||
for (let key in i18n?.services?.resourceStore?.data) {
|
||||
if (key === "en" || key === currentLanguage) {
|
||||
initialI18nStore[key] = i18n.services.resourceStore.data[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assets = await getAssets();
|
||||
|
||||
const { component, styleTags } = renderApp(i18n, initialState, url);
|
||||
|
||||
const htmlString = template(
|
||||
initialState,
|
||||
component,
|
||||
styleTags,
|
||||
initialI18nStore,
|
||||
currentLanguage,
|
||||
assets,
|
||||
t
|
||||
);
|
||||
|
||||
return res.send(htmlString);
|
||||
} catch (e) {
|
||||
let message: string | unknown = e;
|
||||
if (e instanceof Error) {
|
||||
message = e.message;
|
||||
}
|
||||
|
||||
const status = e?.response?.status === 404 ? 404 : 520;
|
||||
|
||||
if (status !== 404 && !initialState.currentColorScheme) {
|
||||
const availableThemes: IThemes = await getAppearanceTheme();
|
||||
|
||||
const currentColorScheme = availableThemes.themes.find((theme) => {
|
||||
return availableThemes.selected === theme.id;
|
||||
});
|
||||
|
||||
initialState.currentColorScheme = currentColorScheme;
|
||||
}
|
||||
|
||||
initialState.error = {
|
||||
status,
|
||||
standalone,
|
||||
message,
|
||||
};
|
||||
|
||||
const { component, styleTags } = renderApp(i18n, initialState, url);
|
||||
|
||||
assets = await getAssets();
|
||||
|
||||
const htmlString = template(
|
||||
initialState,
|
||||
component,
|
||||
styleTags,
|
||||
{},
|
||||
"en",
|
||||
assets,
|
||||
t
|
||||
);
|
||||
|
||||
winston.error(message);
|
||||
|
||||
return res.send(htmlString);
|
||||
}
|
||||
});
|
||||
|
||||
const server = app.listen(port, () => {
|
||||
winston.info(`Server is listening on port ${port}`);
|
||||
});
|
||||
|
||||
if (IS_DEVELOPMENT) {
|
||||
const wss = ws(server);
|
||||
|
||||
const manifestFile = path.resolve(
|
||||
path.join(__dirname, "client/manifest.json")
|
||||
);
|
||||
|
||||
let fsWait = false;
|
||||
let waitTimeout: timeoutType;
|
||||
fs.watch(manifestFile, (event, filename) => {
|
||||
if (filename && event === "change") {
|
||||
if (fsWait) return;
|
||||
fsWait = true;
|
||||
waitTimeout = setTimeout(() => {
|
||||
fsWait = false;
|
||||
clearTimeout(waitTimeout);
|
||||
|
||||
wss.broadcast && wss.broadcast("reload");
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
}
|
@ -1,131 +0,0 @@
|
||||
import { translations } from "../../../autoGeneratedTranslations";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import {
|
||||
getSettings,
|
||||
getBuildVersion,
|
||||
getAuthProviders,
|
||||
getCapabilities,
|
||||
getAppearanceTheme,
|
||||
getLogoUrls,
|
||||
getCurrentSsoSettings,
|
||||
} from "@docspace/shared/api/settings";
|
||||
|
||||
import { getUser } from "@docspace/shared/api/people";
|
||||
|
||||
import { getClient, getScopeList } from "@docspace/shared/api/oauth";
|
||||
|
||||
import { IScope } from "@docspace/shared/utils/oauth/interfaces";
|
||||
|
||||
import { TenantStatus } from "@docspace/shared/enums";
|
||||
|
||||
export const getAssets = (): assetsType => {
|
||||
const manifest = fs.readFileSync(
|
||||
path.join(__dirname, "client/manifest.json"),
|
||||
"utf-8"
|
||||
);
|
||||
|
||||
const assets = JSON.parse(manifest);
|
||||
|
||||
return assets;
|
||||
};
|
||||
|
||||
export const getScripts = (assets: assetsType): string[] | void => {
|
||||
if (!assets || typeof assets !== "object") return;
|
||||
const regTest = /static\/js\/.*/;
|
||||
const keys = [];
|
||||
|
||||
for (let key in assets) {
|
||||
if (assets.hasOwnProperty(key) && regTest.test(key)) {
|
||||
keys.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
return keys;
|
||||
};
|
||||
|
||||
export const loadPath = (language: string, nameSpace: string): string => {
|
||||
const path = translations?.get(language)?.get(nameSpace);
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
export const getInitialState = async (
|
||||
query: MatchType,
|
||||
isAuth: boolean
|
||||
): Promise<IInitialState> => {
|
||||
let portalSettings: IPortalSettings,
|
||||
buildInfo: IBuildInfo,
|
||||
providers: ProvidersType,
|
||||
capabilities: ICapabilities,
|
||||
availableThemes: IThemes,
|
||||
logoUrls: ILogoUrl[],
|
||||
ssoSettings: ISSOSettings;
|
||||
|
||||
const baseSettings = [
|
||||
getSettings(),
|
||||
getBuildVersion(),
|
||||
getAppearanceTheme(),
|
||||
getLogoUrls(),
|
||||
];
|
||||
|
||||
const settings = [getAuthProviders(), getCapabilities()];
|
||||
|
||||
if (!isAuth) settings.push(getCurrentSsoSettings());
|
||||
|
||||
[portalSettings, buildInfo, availableThemes, logoUrls] =
|
||||
await Promise.all(baseSettings);
|
||||
|
||||
if (portalSettings.tenantStatus !== TenantStatus.PortalRestore)
|
||||
[providers, capabilities, ssoSettings] = await Promise.all(settings);
|
||||
|
||||
const currentColorScheme = availableThemes.themes.find((theme) => {
|
||||
return availableThemes.selected === theme.id;
|
||||
});
|
||||
|
||||
const initialState: IInitialState = {
|
||||
portalSettings,
|
||||
buildInfo,
|
||||
providers,
|
||||
capabilities,
|
||||
match: query,
|
||||
currentColorScheme,
|
||||
logoUrls,
|
||||
ssoSettings,
|
||||
};
|
||||
|
||||
return initialState;
|
||||
};
|
||||
|
||||
//TODO: get client by id for links
|
||||
export const getOAuthState = async (
|
||||
clientId: string,
|
||||
isAuth: boolean
|
||||
): Promise<IOAuthState> => {
|
||||
const requests = [];
|
||||
|
||||
requests.push(getClient(clientId, isAuth));
|
||||
|
||||
if (isAuth) {
|
||||
requests.push(getUser());
|
||||
requests.push(getScopeList());
|
||||
}
|
||||
|
||||
const [client, ...rest] = await Promise.all(requests);
|
||||
|
||||
const state: IOAuthState = {
|
||||
clientId,
|
||||
state: "",
|
||||
isConsent: false,
|
||||
client,
|
||||
self: undefined,
|
||||
scopes: undefined,
|
||||
};
|
||||
|
||||
if (isAuth) {
|
||||
state.self = rest[0] as ISelf;
|
||||
state.scopes = rest[1] as IScope[];
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
Loading…
Reference in New Issue
Block a user