mirror of https://github.com/coder/coder.git
85 lines
2.8 KiB
TypeScript
85 lines
2.8 KiB
TypeScript
import type { FC } from "react";
|
|
import { Helmet } from "react-helmet-async";
|
|
import { useQuery } from "react-query";
|
|
import { Navigate, useLocation, useNavigate } from "react-router-dom";
|
|
import { buildInfo } from "api/queries/buildInfo";
|
|
import { authMethods } from "api/queries/users";
|
|
import { useAuthContext } from "contexts/auth/AuthProvider";
|
|
import { getApplicationName } from "utils/appearance";
|
|
import { retrieveRedirect } from "utils/redirect";
|
|
import { LoginPageView } from "./LoginPageView";
|
|
import { appearance } from "api/queries/appearance";
|
|
|
|
export const LoginPage: FC = () => {
|
|
const location = useLocation();
|
|
const {
|
|
isLoading,
|
|
isSignedIn,
|
|
isConfiguringTheFirstUser,
|
|
signIn,
|
|
isSigningIn,
|
|
signInError,
|
|
} = useAuthContext();
|
|
const authMethodsQuery = useQuery(authMethods());
|
|
const redirectTo = retrieveRedirect(location.search);
|
|
const applicationName = getApplicationName();
|
|
const navigate = useNavigate();
|
|
const buildInfoQuery = useQuery(buildInfo());
|
|
const siteConfigQuery = useQuery(appearance());
|
|
|
|
if (isSignedIn) {
|
|
// If the redirect is going to a workspace application, and we
|
|
// are missing authentication, then we need to change the href location
|
|
// to trigger a HTTP request. This allows the BE to generate the auth
|
|
// cookie required. Similarly for the OAuth2 exchange as the authorization
|
|
// page is served by the backend.
|
|
// If no redirect is present, then ignore this branched logic.
|
|
if (redirectTo !== "" && redirectTo !== "/") {
|
|
try {
|
|
// This catches any absolute redirects. Relative redirects
|
|
// will fail the try/catch. Subdomain apps are absolute redirects.
|
|
const redirectURL = new URL(redirectTo);
|
|
if (redirectURL.host !== window.location.host) {
|
|
window.location.href = redirectTo;
|
|
return null;
|
|
}
|
|
} catch {
|
|
// Do nothing
|
|
}
|
|
// Path based apps and OAuth2.
|
|
if (redirectTo.includes("/apps/") || redirectTo.includes("/oauth2/")) {
|
|
window.location.href = redirectTo;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return <Navigate to={redirectTo} replace />;
|
|
}
|
|
|
|
if (isConfiguringTheFirstUser) {
|
|
return <Navigate to="/setup" replace />;
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Helmet>
|
|
<title>Sign in to {applicationName}</title>
|
|
</Helmet>
|
|
<LoginPageView
|
|
authMethods={authMethodsQuery.data}
|
|
error={signInError}
|
|
isLoading={isLoading || authMethodsQuery.isLoading}
|
|
buildInfo={buildInfoQuery.data}
|
|
termsOfService={siteConfigQuery.data?.terms_of_service}
|
|
isSigningIn={isSigningIn}
|
|
onSignIn={async ({ email, password }) => {
|
|
await signIn(email, password);
|
|
navigate("/");
|
|
}}
|
|
/>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default LoginPage;
|