More style changes to login

This commit is contained in:
Vladyslav Matsiiako
2023-05-09 23:24:37 -07:00
parent 4e7145dfe5
commit 1fce8cc769
6 changed files with 141 additions and 144 deletions
+1 -17
View File
@@ -61,22 +61,6 @@ const InputField = ({
<div className="flex-col w-full"> <div className="flex-col w-full">
<div className="flex flex-row text-mineshaft-300 items-center mb-0.5"> <div className="flex flex-row text-mineshaft-300 items-center mb-0.5">
<p className="text-sm font-semibold mr-1">{label}</p> <p className="text-sm font-semibold mr-1">{label}</p>
{/* {label === "Password" && router.asPath !== "/login" && (
<div className="mb-0.5 relative inline-block text-gray-400 underline hover:text-primary duration-200">
<FontAwesomeIcon
icon={faCircleExclamation}
className={`text-sm peer ${
error && "text-red"
}`}
/>
<span className="absolute hidden peer-hover:block duration-200 w-60 -left-28 -top-2 -translate-y-full px-2 py-2 bg-gray-700 rounded-md text-center text-gray-200 text-sm after:content-[''] after:absolute after:left-1/2 after:top-[100%] after:-translate-x-1/2 after:border-8 after:border-x-transparent after:border-b-transparent after:border-t-gray-700">
The password should contain at least 8
characters including at least 1 lowercase
character, uppercase character, number, and a
special character.
</span>
</div>
)} */}
</div> </div>
<div <div
className={`group relative flex flex-col justify-center w-full max-w-2xl border ${ className={`group relative flex flex-col justify-center w-full max-w-2xl border ${
@@ -95,7 +79,7 @@ const InputField = ({
: '' : ''
} ${ } ${
error ? 'focus:ring-red/50' : 'focus:ring-primary/50' error ? 'focus:ring-red/50' : 'focus:ring-primary/50'
} relative peer bg-bunker-800 rounded-md text-gray-400 text-md p-2 w-full min-w-16 outline-none focus:ring-4 duration-200`} } relative peer bg-mineshaft-900 rounded-md text-gray-400 text-md p-2 w-full min-w-16 outline-none focus:ring-4 duration-200`}
name={name} name={name}
spellCheck="false" spellCheck="false"
autoComplete={autoComplete} autoComplete={autoComplete}
@@ -2,8 +2,8 @@ import { useTranslation } from 'next-i18next';
import { faWarning } from '@fortawesome/free-solid-svg-icons'; import { faWarning } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Button from '../basic/buttons/Button';
import issueBackupKey from '../utilities/cryptography/issueBackupKey'; import issueBackupKey from '../utilities/cryptography/issueBackupKey';
import { Button } from '../v2';
interface DownloadBackupPDFStepProps { interface DownloadBackupPDFStepProps {
incrementStep: () => void; incrementStep: () => void;
@@ -30,33 +30,37 @@ export default function DonwloadBackupPDFStep({
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<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-auto mb-36 md:mb-16 rounded-xl drop-shadow-xl"> <div className="flex flex-col items-center w-full h-full px-4 md:px-6 mx-auto mb-36 md:mb-16">
<p className="text-4xl text-center font-semibold flex justify-center text-primary"> <p className="text-xl text-center font-medium flex justify-center text-transparent bg-clip-text bg-gradient-to-b from-white to-bunker-200">
{t('signup:step4-message')} {t('signup:step4-message')}
</p> </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"> <div className="flex flex-col pb-2 bg-mineshaft-900 border border-mineshaft-700 items-center justify-center text-center lg:w-1/6 w-1/4 min-w-[27rem] mt-4 md:mt-8 max-w-md text-bunker-300 text-md rounded-md">
<div>{t('signup:step4-description1')}</div> <div className="w-full px-3 pt-1 mt-8 flex flex-row text-center items-center m-2 text-bunker-300 rounded-md lg:w-1/6 w-1/4 min-w-[26rem] mx-auto">
<div className="mt-3">{t('signup:step4-description2')}</div> <FontAwesomeIcon icon={faWarning} className="ml-2 mr-4 text-5xl my-2" />
</div> <span className='mb-2'>{t('signup:step4-description1')} {t('signup:step4-description3')}</span>
<div className="w-full p-2 flex flex-row items-center bg-white/10 text-gray-400 rounded-md max-w-xs md:max-w-md mx-auto mt-4"> {/* {t('signup:step4-description2')} */}
<FontAwesomeIcon icon={faWarning} className="ml-2 mr-4 text-4xl" /> </div>
{t('signup:step4-description3')} <div className="flex flex-col items-center justify-center mt-4 mb-4 lg:w-1/6 w-1/4 min-w-[20rem] mt-2 md:max-w-md mx-auto text-sm text-center md:text-left">
</div> <div className="text-l py-1 text-lg w-full">
<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
<Button onClick={async () => {
text="Download PDF" await issueBackupKey({
onButtonPressed={async () => { email,
await issueBackupKey({ password,
email, personalName: name,
password, setBackupKeyError: () => { },
personalName: name, setBackupKeyIssued: () => { }
setBackupKeyError: () => { }, });
setBackupKeyIssued: () => { } incrementStep();
}); }}
incrementStep(); size="sm"
}} isFullWidth
size="lg" className='h-12'
/> colorSchema="primary"
variant="outline_bg"
> Download PDF </Button>
</div>
</div>
</div> </div>
</div> </div>
); );
@@ -61,8 +61,6 @@ export default function EnterEmailStep({
onChange={(e) => setEmail(e.target.value)} onChange={(e) => setEmail(e.target.value)}
value={email} value={email}
isRequired isRequired
// error={emailError}
// errorText={emailErrorMessage}
autoComplete="username" autoComplete="username"
className="h-12" className="h-12"
/> />
@@ -39,50 +39,52 @@ export default function TeamInviteStep(): JSX.Element {
}; };
return ( return (
<div className="bg-bunker w-max mx-auto h-7/12 pt-6 pb-4 px-8 rounded-xl drop-shadow-xl mb-64 md:mb-32"> <div className="w-max mx-auto min-w-lg h-full pb-4 px-8 mb-64 md:mb-32">
<p className="text-4xl font-semibold flex justify-center text-primary"> <p className="text-2xl font-semibold flex justify-center text-transparent bg-clip-text bg-gradient-to-b from-white to-bunker-200">
{t('signup:step5-invite-team')} {t('signup:step5-invite-team')}
</p> </p>
<p className="text-center flex justify-center text-bunker-300 max-w-xs md:max-w-sm md:mx-8 mb-6 mt-4"> <p className="text-center flex justify-center text-bunker-400 md:mx-8 mb-6 mt-4">
{t('signup:step5-subtitle')} {t('signup:step5-subtitle')}
</p> </p>
<div> <div className="bg-mineshaft-800 border border-mineshaft-600 w-max mx-auto pt-6 pb-4 px-8 rounded-xl drop-shadow-xl mb-64 md:mb-32">
<div className="overflow-auto bg-bunker-800"> <div>
<div className="whitespace-pre-wrap break-words bg-transparent" /> <div className="text-bunker-300 font-medium pl-1 pb-1 text-sm">
<span>Emails</span>
</div>
<textarea
className="bg-mineshaft-900 min-w-[30rem] h-20 w-full placeholder:text-bunker-400 py-1 px-2 rounded-md border border-mineshaft-500 text-sm text-bunker-300 outline-none focus:ring-2 ring-primary-800 ring-opacity-70"
value={emails}
onChange={(e) => setEmails(e.target.value)}
placeholder="[email protected], [email protected]..."
/>
</div> </div>
<textarea <div className="flex flex-row max-w-max min-w-28 items-center justify-center md:p-2 max-h-24 mx-auto text-lg px-4 mt-4 mb-2">
className="bg-bunker-800 h-20 w-full placeholder:text-bunker-400 py-1 px-2 rounded-md border border-mineshaft-500 text-sm text-bunker-300 outline-none focus:ring-2 ring-primary-800 ring-opacity-70" <div
value={emails} onKeyDown={() => null}
onChange={(e) => setEmails(e.target.value)} role="button"
placeholder="[email protected], [email protected]..." tabIndex={0}
className="text-md md:text-sm mx-3 text-bunker-300 bg-mineshaft-700 py-3 md:py-3.5 px-5 rounded-md cursor-pointer hover:bg-mineshaft-500 duration-200"
onClick={redirectToHome}
>
{t('signup:step5-skip')}
</div>
<Button
text={t('signup:step5-send-invites') ?? ''}
onButtonPressed={() => {
if(serverDetails?.emailConfigured){
inviteUsers({ emails })
}else{
handlePopUpOpen('setUpEmail');
}
}}
size="lg"
/>
</div>
<EmailServiceSetupModal
isOpen={popUp.setUpEmail?.isOpen}
onOpenChange={(isOpen) => handlePopUpToggle('setUpEmail', isOpen)}
/> />
</div> </div>
<div className="flex flex-row max-w-max min-w-28 items-center justify-center md:p-2 max-h-24 mx-auto text-lg px-4 mt-4 mb-2">
<div
onKeyDown={() => null}
role="button"
tabIndex={0}
className="text-md md:text-sm mx-3 text-bunker-300 bg-mineshaft-700 py-3 md:py-3.5 px-5 rounded-md cursor-pointer hover:bg-mineshaft-500 duration-200"
onClick={redirectToHome}
>
{t('signup:step5-skip')}
</div>
<Button
text={t('signup:step5-send-invites') ?? ''}
onButtonPressed={() => {
if(serverDetails?.emailConfigured){
inviteUsers({ emails })
}else{
handlePopUpOpen('setUpEmail');
}
}}
size="lg"
/>
</div>
<EmailServiceSetupModal
isOpen={popUp.setUpEmail?.isOpen}
onOpenChange={(isOpen) => handlePopUpToggle('setUpEmail', isOpen)}
/>
</div> </div>
); );
} }
+58 -52
View File
@@ -2,7 +2,7 @@ import crypto from 'crypto';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { faCheck, faX } from '@fortawesome/free-solid-svg-icons'; import { faCheck, faXmark } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import jsrp from 'jsrp'; import jsrp from 'jsrp';
import nacl from 'tweetnacl'; import nacl from 'tweetnacl';
@@ -19,6 +19,7 @@ import Aes256Gcm from '../utilities/cryptography/aes-256-gcm';
import { deriveArgonKey } from '../utilities/cryptography/crypto'; import { deriveArgonKey } from '../utilities/cryptography/crypto';
import { saveTokenToLocalStorage } from '../utilities/saveTokenToLocalStorage'; import { saveTokenToLocalStorage } from '../utilities/saveTokenToLocalStorage';
import SecurityClient from '../utilities/SecurityClient'; import SecurityClient from '../utilities/SecurityClient';
import { Input } from '../v2';
// eslint-disable-next-line new-cap // eslint-disable-next-line new-cap
const client = new jsrp.client(); const client = new jsrp.client();
@@ -28,10 +29,12 @@ interface UserInfoStepProps {
email: string; email: string;
password: string; password: string;
setPassword: (value: string) => void; setPassword: (value: string) => void;
firstName: string; name: string;
setFirstName: (value: string) => void; setName: (value: string) => void;
lastName: string; organizationName: string;
setLastName: (value: string) => void; setOrganizationName: (value: string) => void;
attributionSource: string;
setAttributionSource: (value: string) => void;
providerAuthToken?: string; providerAuthToken?: string;
} }
@@ -53,14 +56,16 @@ export default function UserInfoStep({
email, email,
password, password,
setPassword, setPassword,
firstName, name,
setFirstName, setName,
lastName, organizationName,
setLastName, setOrganizationName,
attributionSource,
setAttributionSource,
providerAuthToken, providerAuthToken,
}: UserInfoStepProps): JSX.Element { }: UserInfoStepProps): JSX.Element {
const [firstNameError, setFirstNameError] = useState(false); const [nameError, setNameError] = useState(false);
const [lastNameError, setLastNameError] = useState(false); const [organizationNameError, setOrganizationNameError] = useState(false);
const [passwordErrorLength, setPasswordErrorLength] = useState(false); const [passwordErrorLength, setPasswordErrorLength] = useState(false);
const [passwordErrorNumber, setPasswordErrorNumber] = useState(false); const [passwordErrorNumber, setPasswordErrorNumber] = useState(false);
const [passwordErrorLowerCase, setPasswordErrorLowerCase] = useState(false); const [passwordErrorLowerCase, setPasswordErrorLowerCase] = useState(false);
@@ -73,17 +78,17 @@ export default function UserInfoStep({
const signupErrorCheck = async () => { const signupErrorCheck = async () => {
setIsLoading(true); setIsLoading(true);
let errorCheck = false; let errorCheck = false;
if (!firstName) { if (!name) {
setFirstNameError(true); setNameError(true);
errorCheck = true; errorCheck = true;
} else { } else {
setFirstNameError(false); setNameError(false);
} }
if (!lastName) { if (!organizationName) {
setLastNameError(true); setOrganizationNameError(true);
errorCheck = true; errorCheck = true;
} else { } else {
setLastNameError(false); setOrganizationNameError(false);
} }
errorCheck = passwordCheck({ errorCheck = passwordCheck({
password, password,
@@ -149,8 +154,8 @@ export default function UserInfoStep({
const response = await completeAccountInformationSignup({ const response = await completeAccountInformationSignup({
email, email,
firstName, firstName: name.split(" ")[0],
lastName, lastName: name.split(" ")[1],
protectedKey, protectedKey,
protectedKeyIV, protectedKeyIV,
protectedKeyTag, protectedKeyTag,
@@ -161,7 +166,7 @@ export default function UserInfoStep({
providerAuthToken, providerAuthToken,
salt: result.salt, salt: result.salt,
verifier: result.verifier, verifier: result.verifier,
organizationName: `${firstName}'s organization`, organizationName,
}); });
// unset signup JWT token and set JWT token // unset signup JWT token and set JWT token
@@ -202,43 +207,44 @@ export default function UserInfoStep({
}; };
return ( return (
<div className="bg-bunker w-max mx-auto h-7/12 py-10 px-8 rounded-xl drop-shadow-xl mb-36 md:mb-16"> <div className="w-max mx-auto h-full px-8 mb-36 md:mb-16">
<p className="text-4xl font-bold flex justify-center mb-6 mx-8 md:mx-16 text-primary"> <p className="text-xl font-medium flex justify-center mb-6 mx-8 md:mx-16 text-transparent bg-clip-text bg-gradient-to-b from-white to-bunker-200">
{t('signup:step3-message')} Tell us a bit about yourself
</p> </p>
<div className="relative z-0 flex items-center justify-end w-full md:p-2 rounded-lg max-h-24"> <div className="relative z-0 flex flex-col items-center justify-end w-full md:p-2 rounded-lg max-h-24">
<InputField <p className='text-left w-full text-sm text-bunker-300 mb-1 ml-1 font-medium'>Your Name</p>
label={t('common:first-name')} <Input
onChangeHandler={setFirstName} placeholder="Jane Doe"
type="name" onChange={(e) => setName(e.target.value)}
value={firstName} value={name}
isRequired isRequired
errorText={
t('common:validate-required', {
name: t('common:first-name')
}) as string
}
error={firstNameError}
autoComplete="given-name" autoComplete="given-name"
className="h-12"
/> />
{nameError && <p className='text-left w-full text-xs text-red-600 mt-1 ml-1'>Please, specify your name</p>}
</div> </div>
<div className="mt-2 flex items-center justify-center w-full md:p-2 rounded-lg max-h-24"> <div className="relative z-0 flex flex-col items-center justify-end w-full md:p-2 rounded-lg max-h-24">
<InputField <p className='text-left w-full text-sm text-bunker-300 mb-1 ml-1 font-medium'>Organization Name</p>
label={t('common:last-name')} <Input
onChangeHandler={setLastName} placeholder="Infisical"
type="name" onChange={(e) => setOrganizationName(e.target.value)}
value={lastName} value={organizationName}
isRequired isRequired
errorText={ className="h-12"
t('common:validate-required', { />
name: t('common:last-name') {organizationNameError && <p className='text-left w-full text-xs text-red-600 mt-1 ml-1'>Please, specify your organization name</p>}
}) as string </div>
} <div className="relative z-0 flex flex-col items-center justify-end w-full md:p-2 rounded-lg max-h-24">
error={lastNameError} <p className='text-left w-full text-sm text-bunker-300 mb-1 ml-1 font-medium'>Where did you hear about us? <span className="font-light">(optional)</span></p>
autoComplete="family-name" <Input
placeholder=""
onChange={(e) => setAttributionSource(e.target.value)}
value={attributionSource}
isRequired
className="h-12"
/> />
</div> </div>
<div className="mt-2 flex flex-col items-center justify-center w-full md:p-2 rounded-lg max-h-60"> <div className="flex flex-col items-center justify-center w-full md:p-2 rounded-lg max-h-60">
<InputField <InputField
label={t('section-password:password')} label={t('section-password:password')}
onChangeHandler={(pass: string) => { onChangeHandler={(pass: string) => {
@@ -263,7 +269,7 @@ export default function UserInfoStep({
<div className="text-gray-400 text-sm mb-1">{t('section-password:validate-base')}</div> <div className="text-gray-400 text-sm mb-1">{t('section-password:validate-base')}</div>
<div className="flex flex-row justify-start items-center ml-1"> <div className="flex flex-row justify-start items-center ml-1">
{passwordErrorLength ? ( {passwordErrorLength ? (
<FontAwesomeIcon icon={faX} className="text-md text-red mr-2.5" /> <FontAwesomeIcon icon={faXmark} className="text-md text-red ml-0.5 mr-2.5" />
) : ( ) : (
<FontAwesomeIcon icon={faCheck} className="text-md text-primary mr-2" /> <FontAwesomeIcon icon={faCheck} className="text-md text-primary mr-2" />
)} )}
@@ -273,7 +279,7 @@ export default function UserInfoStep({
</div> </div>
<div className="flex flex-row justify-start items-center ml-1"> <div className="flex flex-row justify-start items-center ml-1">
{passwordErrorLowerCase ? ( {passwordErrorLowerCase ? (
<FontAwesomeIcon icon={faX} className="text-md text-red mr-2.5" /> <FontAwesomeIcon icon={faXmark} className="text-md text-red ml-0.5 mr-2.5" />
) : ( ) : (
<FontAwesomeIcon icon={faCheck} className="text-md text-primary mr-2" /> <FontAwesomeIcon icon={faCheck} className="text-md text-primary mr-2" />
)} )}
@@ -285,7 +291,7 @@ export default function UserInfoStep({
</div> </div>
<div className="flex flex-row justify-start items-center ml-1"> <div className="flex flex-row justify-start items-center ml-1">
{passwordErrorNumber ? ( {passwordErrorNumber ? (
<FontAwesomeIcon icon={faX} className="text-md text-red mr-2.5" /> <FontAwesomeIcon icon={faXmark} className="text-md text-red ml-0.5 mr-2.5" />
) : ( ) : (
<FontAwesomeIcon icon={faCheck} className="text-md text-primary mr-2" /> <FontAwesomeIcon icon={faCheck} className="text-md text-primary mr-2" />
)} )}
+13 -10
View File
@@ -25,11 +25,12 @@ import getWorkspaces from './api/workspace/getWorkspaces';
export default function SignUp() { export default function SignUp() {
const [email, setEmail] = useState(''); const [email, setEmail] = useState('');
const [password, setPassword] = useState(''); const [password, setPassword] = useState('');
const [firstName, setFirstName] = useState(''); const [name, setName] = useState('');
const [lastName, setLastName] = useState(''); const [organizationName, setOrganizationName] = useState('');
const [attributionSource, setAttributionSource] = useState('');
const [code, setCode] = useState('123456'); const [code, setCode] = useState('123456');
const [codeError, setCodeError] = useState(false); const [codeError, setCodeError] = useState(false);
const [step, setStep] = useState(1); const [step, setStep] = useState(5);
const router = useRouter(); const router = useRouter();
const { data: serverDetails } = useFetchServerStatus(); const { data: serverDetails } = useFetchServerStatus();
const [isSignupWithEmail, setIsSignupWithEmail] = useState(false); const [isSignupWithEmail, setIsSignupWithEmail] = useState(false);
@@ -124,10 +125,12 @@ export default function SignUp() {
email={email || providerEmail} email={email || providerEmail}
password={password} password={password}
setPassword={setPassword} setPassword={setPassword}
firstName={firstName} name={name}
setFirstName={setFirstName} setName={setName}
lastName={lastName} organizationName={organizationName}
setLastName={setLastName} setOrganizationName={setOrganizationName}
attributionSource={attributionSource}
setAttributionSource={setAttributionSource}
providerAuthToken={providerAuthToken} providerAuthToken={providerAuthToken}
/> />
) )
@@ -139,14 +142,14 @@ export default function SignUp() {
incrementStep={incrementStep} incrementStep={incrementStep}
email={email || providerEmail} email={email || providerEmail}
password={password} password={password}
name={`${firstName} ${lastName}`} name={name}
/> />
) )
} }
if (serverDetails?.emailConfigured) { // if (serverDetails?.emailConfigured) {
return <TeamInviteStep /> return <TeamInviteStep />
} // }
return "" return ""
} }