mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-15 12:38:36 +00:00
Merge pull request #535 from sheensantoscapadngan/feature/google-signin-signup-integration
Feature/google signin signup integration
This commit is contained in:
@@ -57,9 +57,11 @@ const App = ({ Component, pageProps, ...appProps }: NextAppProp): JSX.Element =>
|
||||
) {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<AuthProvider>
|
||||
<Component {...pageProps} />
|
||||
</AuthProvider>
|
||||
<NotificationProvider>
|
||||
<AuthProvider>
|
||||
<Component {...pageProps} />
|
||||
</AuthProvider>
|
||||
</NotificationProvider>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ interface Props {
|
||||
protectedKey: string;
|
||||
protectedKeyIV: string;
|
||||
protectedKeyTag: string;
|
||||
providerAuthToken?: string;
|
||||
publicKey: string;
|
||||
encryptedPrivateKey: string;
|
||||
encryptedPrivateKeyIV: string;
|
||||
@@ -15,6 +16,7 @@ interface Props {
|
||||
organizationName: string;
|
||||
salt: string;
|
||||
verifier: string;
|
||||
attributionSource?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,9 +51,11 @@ const completeAccountInformationSignup = async ({
|
||||
encryptedPrivateKeyTag,
|
||||
salt,
|
||||
verifier,
|
||||
organizationName
|
||||
organizationName,
|
||||
providerAuthToken,
|
||||
attributionSource
|
||||
}: Props) => {
|
||||
const { data } = await apiRequest.post('/api/v2/signup/complete-account/signup', {
|
||||
const { data } = await apiRequest.post('/api/v3/signup/complete-account/signup', {
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
@@ -64,7 +68,9 @@ const completeAccountInformationSignup = async ({
|
||||
encryptedPrivateKeyTag,
|
||||
salt,
|
||||
verifier,
|
||||
organizationName
|
||||
organizationName,
|
||||
providerAuthToken,
|
||||
attributionSource,
|
||||
});
|
||||
|
||||
return data;
|
||||
|
||||
@@ -9,16 +9,17 @@ interface Login1 {
|
||||
* @param {*} clientPublicKey
|
||||
* @returns
|
||||
*/
|
||||
const login1 = async (email: string, clientPublicKey: string) => {
|
||||
const response = await fetch("/api/v2/auth/login1", {
|
||||
const login1 = async (loginDetails: {
|
||||
email: string;
|
||||
clientPublicKey: string;
|
||||
providerAuthToken?: string;
|
||||
}) => {
|
||||
const response = await fetch("/api/v3/auth/login1", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
clientPublicKey,
|
||||
}),
|
||||
body: JSON.stringify(loginDetails),
|
||||
});
|
||||
// need precise error handling about the status code
|
||||
if (response?.status === 200) {
|
||||
|
||||
@@ -17,16 +17,17 @@ interface Login2Response {
|
||||
* @param {*} clientPublicKey
|
||||
* @returns
|
||||
*/
|
||||
const login2 = async (email: string, clientProof: string) => {
|
||||
const response = await fetch('/api/v2/auth/login2', {
|
||||
const login2 = async (loginDetails: {
|
||||
email: string;
|
||||
clientProof: string;
|
||||
providerAuthToken?: string;
|
||||
}) => {
|
||||
const response = await fetch('/api/v3/auth/login2', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
clientProof
|
||||
}),
|
||||
body: JSON.stringify(loginDetails),
|
||||
credentials: 'include'
|
||||
});
|
||||
// need precise error handling about the status code
|
||||
|
||||
@@ -5,9 +5,12 @@ import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
import ListBox from '@app/components/basic/Listbox';
|
||||
// import ListBox from '@app/components/basic/Listbox';
|
||||
import InitialLoginStep from '@app/components/login/InitialLoginStep';
|
||||
import LoginStep from '@app/components/login/LoginStep';
|
||||
import MFAStep from '@app/components/login/MFAStep';
|
||||
import PasswordInputStep from '@app/components/login/PasswordInputStep';
|
||||
import { useProviderAuth } from '@app/hooks/useProviderAuth';
|
||||
import { isLoggedIn } from '@app/reactQuery';
|
||||
|
||||
import getWorkspaces from './api/workspace/getWorkspaces';
|
||||
@@ -18,12 +21,23 @@ export default function Login() {
|
||||
const [password, setPassword] = useState('');
|
||||
const [step, setStep] = useState(1);
|
||||
const { t } = useTranslation();
|
||||
const lang = router.locale ?? 'en';
|
||||
// const lang = router.locale ?? 'en';
|
||||
const [isLoginWithEmail, setIsLoginWithEmail] = useState(false);
|
||||
const {
|
||||
providerAuthToken,
|
||||
email: providerEmail,
|
||||
setProviderAuthToken,
|
||||
isProviderUserCompleted
|
||||
} = useProviderAuth();
|
||||
|
||||
const setLanguage = async (to: string) => {
|
||||
router.push('/login', '/login', { locale: to });
|
||||
localStorage.setItem('lang', to);
|
||||
};
|
||||
if (providerAuthToken && isProviderUserCompleted === false) {
|
||||
router.push(`/signup?providerAuthToken=${encodeURIComponent(providerAuthToken)}`);
|
||||
}
|
||||
|
||||
// const setLanguage = async (to: string) => {
|
||||
// router.push('/login', '/login', { locale: to });
|
||||
// localStorage.setItem('lang', to);
|
||||
// };
|
||||
|
||||
useEffect(() => {
|
||||
// TODO(akhilmhdh): workspace will be controlled by a workspace context
|
||||
@@ -42,29 +56,51 @@ export default function Login() {
|
||||
}
|
||||
}, []);
|
||||
|
||||
const renderStep = (loginStep: number) => {
|
||||
// TODO: add MFA step
|
||||
switch (loginStep) {
|
||||
case 1:
|
||||
return (
|
||||
<LoginStep
|
||||
email={email}
|
||||
setEmail={setEmail}
|
||||
password={password}
|
||||
setPassword={setPassword}
|
||||
setStep={setStep}
|
||||
/>
|
||||
);
|
||||
case 2:
|
||||
// TODO: add MFA step
|
||||
return <MFAStep email={email} password={password} />;
|
||||
default:
|
||||
return <div />;
|
||||
const renderView = (loginStep: number) => {
|
||||
if (providerAuthToken && step === 1) {
|
||||
return (
|
||||
<PasswordInputStep
|
||||
email={providerEmail}
|
||||
password={password}
|
||||
providerAuthToken={providerAuthToken}
|
||||
setPassword={setPassword}
|
||||
setProviderAuthToken={setProviderAuthToken}
|
||||
setStep={setStep}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (isLoginWithEmail && loginStep === 1) {
|
||||
return (
|
||||
<LoginStep
|
||||
email={email}
|
||||
setEmail={setEmail}
|
||||
password={password}
|
||||
setPassword={setPassword}
|
||||
setStep={setStep}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (!isLoginWithEmail && loginStep === 1) {
|
||||
return <InitialLoginStep setIsLoginWithEmail={setIsLoginWithEmail} />;
|
||||
}
|
||||
|
||||
if (step === 2) {
|
||||
return (
|
||||
<MFAStep
|
||||
email={email || providerEmail}
|
||||
password={password}
|
||||
providerAuthToken={providerAuthToken}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <div />;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-screen flex-col justify-start bg-bunker-800 px-6">
|
||||
<div className="flex h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28 ">
|
||||
<Head>
|
||||
<title>{t('common.head-title', { title: t('login.title') })}</title>
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
@@ -73,12 +109,12 @@ export default function Login() {
|
||||
<meta name="og:description" content={t('login.og-description') ?? ''} />
|
||||
</Head>
|
||||
<Link href="/">
|
||||
<div className="mb-8 mt-20 flex cursor-pointer justify-center">
|
||||
<Image src="/images/biglogo.png" height={90} width={120} alt="long logo" />
|
||||
<div className="mb-4 mt-20 flex justify-center">
|
||||
<Image src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical logo" />
|
||||
</div>
|
||||
</Link>
|
||||
{renderStep(step)}
|
||||
<div className="absolute right-4 top-0 mt-4 flex items-center justify-center">
|
||||
{renderView(step)}
|
||||
{/* <div className="absolute right-4 top-0 mt-4 flex items-center justify-center">
|
||||
<div className="mx-auto w-48">
|
||||
<ListBox
|
||||
isSelected={lang}
|
||||
@@ -88,7 +124,7 @@ export default function Login() {
|
||||
text={`${t('common.language')}: `}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { useEffect } from "react";
|
||||
|
||||
export default function LoginProviderError() {
|
||||
useEffect(() => {
|
||||
window.localStorage.setItem('PROVIDER_AUTH_ERROR', 'err');
|
||||
window.close();
|
||||
}, [])
|
||||
|
||||
return <div />
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { useEffect } from "react";
|
||||
import { useRouter } from "next/router"
|
||||
|
||||
import SecurityClient from '@app/components/utilities/SecurityClient';
|
||||
|
||||
export default function LoginProviderSuccess() {
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
const { token } = router.query;
|
||||
SecurityClient.setProviderAuthToken(token as string);
|
||||
window.close();
|
||||
}, [])
|
||||
|
||||
return <div />
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Head from 'next/head';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
import { Button, Input } from '@app/components/v2';
|
||||
import { isLoggedIn } from '@app/reactQuery';
|
||||
|
||||
import getWorkspaces from './api/workspace/getWorkspaces';
|
||||
|
||||
export default function Login() {
|
||||
const router = useRouter();
|
||||
const [password, setPassword] = useState('');
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
// TODO(akhilmhdh): workspace will be controlled by a workspace context
|
||||
const redirectToDashboard = async () => {
|
||||
let userWorkspace;
|
||||
try {
|
||||
const userWorkspaces = await getWorkspaces();
|
||||
userWorkspace = userWorkspaces[0] && userWorkspaces[0]._id;
|
||||
router.push(`/dashboard/${userWorkspace}`);
|
||||
} catch (error) {
|
||||
console.log('Error - Not logged in yet');
|
||||
}
|
||||
};
|
||||
if (isLoggedIn()) {
|
||||
redirectToDashboard();
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="flex h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28 ">
|
||||
<Head>
|
||||
<title>{t('common.head-title', { title: t('login.title') })}</title>
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
<meta property="og:image" content="/images/message.png" />
|
||||
<meta property="og:title" content={t('login.og-title') ?? ''} />
|
||||
<meta name="og:description" content={t('login.og-description') ?? ''} />
|
||||
</Head>
|
||||
<Link href="/">
|
||||
<div className="mb-4 mt-20 flex justify-center">
|
||||
<Image src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical logo" />
|
||||
</div>
|
||||
</Link>
|
||||
<div className="mx-auto w-full max-w-md px-6">
|
||||
<p className="mx-auto mb-6 flex w-max justify-center text-xl font-medium text-transparent bg-clip-text bg-gradient-to-b from-white to-bunker-200 text-center mb-8">
|
||||
What’s your email?
|
||||
</p>
|
||||
<div className="relative flex items-center justify-center lg:w-1/6 w-1/4 min-w-[22rem] mx-auto w-full rounded-lg max-h-24 md:max-h-28">
|
||||
<div className="flex items-center justify-center w-full rounded-lg max-h-24 md:max-h-28">
|
||||
<Input
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
type="password"
|
||||
placeholder="Enter your email..."
|
||||
isRequired
|
||||
autoComplete="email"
|
||||
id="email"
|
||||
className="h-12"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className='lg:w-1/6 w-1/4 w-full mx-auto flex items-center justify-center min-w-[22rem] text-center rounded-md mt-4'>
|
||||
<Button
|
||||
colorSchema="primary"
|
||||
variant="outline_bg"
|
||||
onClick={() => {}}
|
||||
isFullWidth
|
||||
className="h-14"
|
||||
>
|
||||
{t('login.login')}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex flex-row items-center justify-center mt-4">
|
||||
<button
|
||||
onClick={() => {router.push('/login')}}
|
||||
type="button"
|
||||
className="text-bunker-300 text-sm hover:underline mt-2 hover:underline-offset-4 hover:decoration-primary-700 hover:text-bunker-200 duration-200 cursor-pointer"
|
||||
>
|
||||
{t('login.other-option')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -3,16 +3,17 @@ import { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Head from 'next/head';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
import CodeInputStep from '@app/components/signup/CodeInputStep';
|
||||
import DownloadBackupPDF from '@app/components/signup/DonwloadBackupPDFStep';
|
||||
import EnterEmailStep from '@app/components/signup/EnterEmailStep';
|
||||
import InitialSignupStep from '@app/components/signup/InitialSignupStep';
|
||||
import TeamInviteStep from '@app/components/signup/TeamInviteStep';
|
||||
import UserInfoStep from '@app/components/signup/UserInfoStep';
|
||||
import SecurityClient from '@app/components/utilities/SecurityClient';
|
||||
import { useFetchServerStatus } from '@app/hooks/api/serverDetails';
|
||||
import { useProviderAuth } from '@app/hooks/useProviderAuth';
|
||||
|
||||
import checkEmailVerificationCode from './api/auth/CheckEmailVerificationCode';
|
||||
import getWorkspaces from './api/workspace/getWorkspaces';
|
||||
@@ -23,15 +24,26 @@ import getWorkspaces from './api/workspace/getWorkspaces';
|
||||
export default function SignUp() {
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [firstName, setFirstName] = useState('');
|
||||
const [lastName, setLastName] = useState('');
|
||||
const [name, setName] = useState('');
|
||||
const [organizationName, setOrganizationName] = useState('');
|
||||
const [attributionSource, setAttributionSource] = useState('');
|
||||
const [code, setCode] = useState('123456');
|
||||
const [codeError, setCodeError] = useState(false);
|
||||
const [step, setStep] = useState(1);
|
||||
const router = useRouter();
|
||||
const { data: serverDetails } = useFetchServerStatus();
|
||||
|
||||
const [isSignupWithEmail, setIsSignupWithEmail] = useState(false);
|
||||
const [isCodeInputCheckLoading, setIsCodeInputCheckLoading] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
const { email: providerEmail, providerAuthToken, isProviderUserCompleted } = useProviderAuth();
|
||||
|
||||
if (providerAuthToken && isProviderUserCompleted) {
|
||||
router.push(`/login?providerAuthToken=${encodeURIComponent(providerAuthToken)}`);
|
||||
}
|
||||
|
||||
if (providerAuthToken && step < 3) {
|
||||
setStep(3);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const tryAuth = async () => {
|
||||
@@ -57,6 +69,7 @@ export default function SignUp() {
|
||||
if (step === 1 || step === 3 || step === 4) {
|
||||
setStep(step + 1);
|
||||
} else if (step === 2) {
|
||||
setIsCodeInputCheckLoading(true);
|
||||
// Checking if the code matches the email.
|
||||
const response = await checkEmailVerificationCode({ email, code });
|
||||
if (response.status === 200) {
|
||||
@@ -66,6 +79,7 @@ export default function SignUp() {
|
||||
} else {
|
||||
setCodeError(true);
|
||||
}
|
||||
setIsCodeInputCheckLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -82,8 +96,65 @@ export default function SignUp() {
|
||||
}
|
||||
}, [step]);
|
||||
|
||||
const renderView = (registerStep: number) => {
|
||||
if (isSignupWithEmail && registerStep === 1) {
|
||||
return <EnterEmailStep email={email} setEmail={setEmail} incrementStep={incrementStep} />;
|
||||
}
|
||||
|
||||
if (!isSignupWithEmail && registerStep === 1) {
|
||||
return <InitialSignupStep setIsSignupWithEmail={setIsSignupWithEmail} />;
|
||||
}
|
||||
|
||||
if (registerStep === 2) {
|
||||
return (
|
||||
<CodeInputStep
|
||||
email={email}
|
||||
incrementStep={incrementStep}
|
||||
setCode={setCode}
|
||||
codeError={codeError}
|
||||
isCodeInputCheckLoading={isCodeInputCheckLoading}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (registerStep === 3) {
|
||||
return (
|
||||
<UserInfoStep
|
||||
incrementStep={incrementStep}
|
||||
email={email || providerEmail}
|
||||
password={password}
|
||||
setPassword={setPassword}
|
||||
name={name}
|
||||
setName={setName}
|
||||
organizationName={organizationName}
|
||||
setOrganizationName={setOrganizationName}
|
||||
attributionSource={attributionSource}
|
||||
setAttributionSource={setAttributionSource}
|
||||
providerAuthToken={providerAuthToken}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (registerStep === 4) {
|
||||
return (
|
||||
<DownloadBackupPDF
|
||||
incrementStep={incrementStep}
|
||||
email={email || providerEmail}
|
||||
password={password}
|
||||
name={name}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (serverDetails?.emailConfigured) {
|
||||
return <TeamInviteStep />;
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-screen flex-col items-center justify-center bg-bunker-800">
|
||||
<div className="flex min-h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28 ">
|
||||
<Head>
|
||||
<title>{t('common.head-title', { title: t('signup.title') })}</title>
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
@@ -91,47 +162,10 @@ export default function SignUp() {
|
||||
<meta property="og:title" content={t('signup.og-title') as string} />
|
||||
<meta name="og:description" content={t('signup.og-description') as string} />
|
||||
</Head>
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<Link href="/">
|
||||
<div className="mb-2 flex cursor-pointer justify-center md:mb-8">
|
||||
<Image src="/images/biglogo.png" height={90} width={120} alt="Infisical Wide Logo" />
|
||||
</div>
|
||||
</Link>
|
||||
<form onSubmit={(e) => e.preventDefault()}>
|
||||
{step === 1 ? (
|
||||
<EnterEmailStep email={email} setEmail={setEmail} incrementStep={incrementStep} />
|
||||
) : step === 2 ? (
|
||||
<CodeInputStep
|
||||
email={email}
|
||||
incrementStep={incrementStep}
|
||||
setCode={setCode}
|
||||
codeError={codeError}
|
||||
/>
|
||||
) : step === 3 ? (
|
||||
<UserInfoStep
|
||||
incrementStep={incrementStep}
|
||||
email={email}
|
||||
password={password}
|
||||
setPassword={setPassword}
|
||||
firstName={firstName}
|
||||
setFirstName={setFirstName}
|
||||
lastName={lastName}
|
||||
setLastName={setLastName}
|
||||
/>
|
||||
) : step === 4 ? (
|
||||
<DownloadBackupPDF
|
||||
incrementStep={incrementStep}
|
||||
email={email}
|
||||
password={password}
|
||||
name={`${firstName} ${lastName}`}
|
||||
/>
|
||||
) : serverDetails?.emailConfigured ? (
|
||||
<TeamInviteStep />
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</form>
|
||||
<div className="mb-4 mt-20 flex justify-center">
|
||||
<Image src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical Logo" />
|
||||
</div>
|
||||
<form onSubmit={(e) => e.preventDefault()}>{renderView(step)}</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ export default function SignupInvite() {
|
||||
|
||||
// Step 4 of the sign up process (download the emergency kit pdf)
|
||||
const stepConfirmEmail = (
|
||||
<div className="bg-bunker flex flex-col items-center w-full max-w-xs md:max-w-lg h-7/12 py-8 px-4 md:px-6 mx-1 mb-36 md:mb-16 rounded-xl drop-shadow-xl">
|
||||
<div className="border border-mineshaft-600 bg-mineshaft-800 flex flex-col items-center w-full max-w-xs md:max-w-lg h-7/12 py-8 px-4 md:px-6 mx-1 mb-36 md:mb-16 rounded-xl drop-shadow-xl">
|
||||
<p className="text-4xl text-center font-semibold mb-6 flex justify-center text-primary-100">
|
||||
Confirm your email
|
||||
</p>
|
||||
@@ -219,8 +219,8 @@ export default function SignupInvite() {
|
||||
|
||||
// Because this is the invite signup - we directly go to the last step of signup (email is already verified)
|
||||
const main = (
|
||||
<div className="bg-bunker w-max mx-auto h-7/12 py-10 px-8 rounded-xl drop-shadow-xl mb-32 md:mb-16">
|
||||
<p className="text-4xl font-bold flex justify-center mb-6 text-gray-400 mx-8 md:mx-16 text-transparent bg-clip-text bg-gradient-to-br from-sky-400 to-primary">
|
||||
<div className="border border-mineshaft-600 bg-mineshaft-800 w-max mx-auto h-7/12 py-10 px-8 rounded-xl drop-shadow-xl mb-32 md:mb-16">
|
||||
<p className="text-4xl font-bold flex justify-center mb-6 mx-8 md:mx-16 text-transparent bg-clip-text bg-gradient-to-tr from-mineshaft-300 to-white">
|
||||
Almost there!
|
||||
</p>
|
||||
<div className="relative z-0 flex items-center justify-end w-full md:p-2 rounded-lg max-h-24">
|
||||
@@ -322,8 +322,8 @@ export default function SignupInvite() {
|
||||
|
||||
// Step 4 of the sign up process (download the emergency kit pdf)
|
||||
const step4 = (
|
||||
<div className="bg-bunker flex flex-col items-center w-full max-w-xs md:max-w-lg h-7/12 py-8 px-4 md:px-6 mx-1 mb-36 md:mb-16 rounded-xl drop-shadow-xl">
|
||||
<p className="text-4xl text-center font-semibold flex justify-center text-transparent bg-clip-text bg-gradient-to-br from-sky-400 to-primary">
|
||||
<div className="border border-mineshaft-600 bg-mineshaft-800 flex flex-col items-center w-full max-w-xs md:max-w-lg h-7/12 pt-8 pb-6 px-4 md:px-6 mx-1 mb-36 md:mb-16 rounded-xl drop-shadow-xl">
|
||||
<p className="text-4xl text-center font-semibold flex justify-center text-transparent bg-clip-text bg-gradient-to-br from-white to-mineshaft-300">
|
||||
Save your Emergency Kit
|
||||
</p>
|
||||
<div className="flex flex-col items-center justify-center w-full mt-4 md:mt-8 max-w-md text-gray-400 text-md rounded-md px-2">
|
||||
@@ -336,7 +336,7 @@ export default function SignupInvite() {
|
||||
<FontAwesomeIcon icon={faWarning} className="ml-2 mr-4 text-4xl" />
|
||||
It contains your Secret Key which we cannot access or recover for you if you lose it.
|
||||
</div>
|
||||
<div className="flex flex-col items-center justify-center md:px-4 md:py-5 mt-2 px-2 py-3 max-h-24 max-w-max mx-auto text-lg">
|
||||
<div className="flex flex-col items-center justify-center md:px-4 md:py-5 mt-4 px-2 py-3 max-h-24 max-w-max mx-auto text-lg">
|
||||
<Button
|
||||
text="Download PDF"
|
||||
onButtonPressed={async () => {
|
||||
@@ -368,14 +368,14 @@ export default function SignupInvite() {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="bg-bunker-800 h-screen flex flex-col items-center justify-center">
|
||||
<div className="bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 h-screen flex flex-col items-center justify-center">
|
||||
<Head>
|
||||
<title>Sign Up</title>
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
</Head>
|
||||
<Link href="/">
|
||||
<div className="flex justify-center mb-2 md:mb-4 opacity-80 cursor-pointer">
|
||||
<Image src="/images/biglogo.png" height={90} width={120} alt="Infisical Wide Logo" />
|
||||
<div className="mb-4 mt-20 flex justify-center">
|
||||
<Image src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical Logo" />
|
||||
</div>
|
||||
</Link>
|
||||
{step === 1 ? stepConfirmEmail : step === 2 ? main : step4}
|
||||
|
||||
Reference in New Issue
Block a user