diff --git a/.circleci/config.yml b/.circleci/config.yml index 6a74a8ad7..6a8a8d974 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -234,7 +234,6 @@ workflows: ignore: - master - qa - - profiles-app - build-qa: context: org-global @@ -242,7 +241,6 @@ workflows: branches: only: - qa - - profiles-app - build-prod: context: org-global @@ -261,7 +259,7 @@ workflows: - dev - justin_fixes - talent_search_fixes - - PROD-4398_integrate-userflow-remove-sprig + - feature/standardized-skills - deployQa: context: org-global diff --git a/package.json b/package.json index 2ef92fbc4..584a7f6a9 100644 --- a/package.json +++ b/package.json @@ -246,5 +246,9 @@ } } ] + }, + "volta": { + "node": "16.15.0", + "yarn": "1.22.19" } } diff --git a/src/apps/accounts/src/lib/assets/security/credential.png b/src/apps/accounts/src/lib/assets/security/credential.png new file mode 100644 index 000000000..914e8d04f Binary files /dev/null and b/src/apps/accounts/src/lib/assets/security/credential.png differ diff --git a/src/apps/accounts/src/lib/assets/security/index.ts b/src/apps/accounts/src/lib/assets/security/index.ts index 8b87173a7..4559e27b4 100644 --- a/src/apps/accounts/src/lib/assets/security/index.ts +++ b/src/apps/accounts/src/lib/assets/security/index.ts @@ -1,6 +1,6 @@ import { ReactComponent as MFAImage } from './mfa.svg' import { ReactComponent as AppleStore } from './apple-store.svg' -import { ReactComponent as UnSuccessfullDiceVerificationIcon } from './unsuccessful.svg' +import credentialImage from './credential.png' import diceIdLogo from './dicelogo.png' import diceIdLogoBig from './dicelogobig.png' import diceIdLogoSmall from './dicelogosmall.png' @@ -8,10 +8,10 @@ import googlePlay from './google-play.png' export { AppleStore, + credentialImage, diceIdLogo, diceIdLogoBig, diceIdLogoSmall, googlePlay, MFAImage, - UnSuccessfullDiceVerificationIcon, } diff --git a/src/apps/accounts/src/settings/tabs/account/security/Security.tsx b/src/apps/accounts/src/settings/tabs/account/security/Security.tsx index f8a608d40..f521783bf 100644 --- a/src/apps/accounts/src/settings/tabs/account/security/Security.tsx +++ b/src/apps/accounts/src/settings/tabs/account/security/Security.tsx @@ -1,9 +1,8 @@ import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react' import { toast } from 'react-toastify' import { KeyedMutator } from 'swr' -import { noop } from 'lodash' -import { Button, Collapsible, FormToggleSwitch, IconSolid, Tooltip } from '~/libs/ui' +import { Button, Collapsible, FormToggleSwitch } from '~/libs/ui' import { diceIdLogo, MFAImage, SettingSection, triggerSurvey } from '~/apps/accounts/src/lib' import { MemberMFAStatus, updateMemberMFAStatusAsync, useMemberMFAStatus, UserProfile } from '~/libs/core' @@ -23,10 +22,12 @@ const Security: FC = (props: SecurityProps) => { } = useMemberMFAStatus(props.profile.userId) const [mfaEnabled, setMFAEnabled]: [boolean, Dispatch>] = useState(false) + const [diceEnabled, setDiceEnabled]: [boolean, Dispatch>] = useState(false) useEffect(() => { if (mfaStatusData) { setMFAEnabled(mfaStatusData.mfaEnabled) + setDiceEnabled(mfaStatusData.diceEnabled) } }, [mfaStatusData]) @@ -36,8 +37,9 @@ const Security: FC = (props: SecurityProps) => { mfaEnabled: !mfaEnabled, }, }) - .then(() => { - setMFAEnabled(!mfaEnabled) + .then(response => { + setMFAEnabled(response.result.content.mfaEnabled) + setDiceEnabled(response.result.content.diceEnabled) toast.success('Your Multi Factor Authentication (MFA) status was updated.') triggerSurvey() }) @@ -46,6 +48,27 @@ const Security: FC = (props: SecurityProps) => { }) } + function handleUserDiceChange(): void { + if (!diceEnabled) { + return + } + + updateMemberMFAStatusAsync(props.profile.userId, { + param: { + diceEnabled: !diceEnabled, + }, + }) + .then(response => { + setMFAEnabled(response.result.content.mfaEnabled) + setDiceEnabled(response.result.content.diceEnabled) + toast.success('Your DICE credential was disabled.') + triggerSurvey() + }) + .catch(() => { + toast.error('Something went wrong. Please try again later.') + }) + } + function handleDiceModalStatus(): void { setSetupDiceModalOpen(!setupDiceModalOpen) } @@ -70,7 +93,6 @@ const Security: FC = (props: SecurityProps) => { name='mfaStatus' onChange={handleUserMFAChange} value={mfaEnabled} - disabled={mfaStatusData?.diceEnabled} /> )} /> @@ -86,12 +108,11 @@ const Security: FC = (props: SecurityProps) => { actionElement={(
{ - mfaStatusData?.diceEnabled ? ( + diceEnabled ? ( ) : (
)} /> diff --git a/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/index.tsx b/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/index.tsx new file mode 100644 index 000000000..07e3f7075 --- /dev/null +++ b/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/ConnectionHandler/index.tsx @@ -0,0 +1,24 @@ +import { FC, useEffect } from 'react' + +import { DiceConnectionStatus, useDiceIdConnection } from '~/libs/core' + +interface ConnectionHandlerProps { + onChange: (newStatus: DiceConnectionStatus) => void; + userId: number; +} + +export const ConnectionHandler: FC = ( + props: ConnectionHandlerProps, +) => { + const diceConnection: DiceConnectionStatus | undefined = useDiceIdConnection(props.userId) + + useEffect(() => { + if (diceConnection) { + props.onChange(diceConnection) + } + }, [diceConnection, props]) + + return ( + <> + ) +} diff --git a/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/DiceSetupModal.module.scss b/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/DiceSetupModal.module.scss index dd1329b65..0fe6f3dec 100644 --- a/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/DiceSetupModal.module.scss +++ b/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/DiceSetupModal.module.scss @@ -34,6 +34,12 @@ margin: auto; } + .credentialImage { + height: 280px; + width: 400px; + align-self: center; + } + .diceBigLogo { margin: $sp-4 0; } diff --git a/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/DiceSetupModal.tsx b/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/DiceSetupModal.tsx index 6f3d6a2e9..1b03bce41 100644 --- a/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/DiceSetupModal.tsx +++ b/src/apps/accounts/src/settings/tabs/account/security/dice-setup-modal/DiceSetupModal.tsx @@ -1,25 +1,24 @@ -import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react' +/* eslint-disable complexity */ +import { Dispatch, FC, SetStateAction, useState } from 'react' import { QRCodeSVG } from 'qrcode.react' -import { get, isUndefined, lowerCase } from 'lodash' import { toast } from 'react-toastify' import { KeyedMutator } from 'swr' import { BaseModal, Button } from '~/libs/ui' import { AppleStore, + credentialImage, diceIdLogoBig, diceIdLogoSmall, googlePlay, - UnSuccessfullDiceVerificationIcon, } from '~/apps/accounts/src/lib' -import { DiceConnectionStatus, updateMemberMFAStatusAsync, useDiceIdConnection, UserProfile } from '~/libs/core' -import { EnvironmentConfig } from '~/config' +import { DiceConnectionStatus, UserProfile } from '~/libs/core' -import { VerificationListener } from './VerificationListener' +import { ConnectionHandler } from './ConnectionHandler' import styles from './DiceSetupModal.module.scss' const GooglePlayLink: string = 'https://play.google.com/store/apps/details?id=com.diwallet1' -const AppleStoreLink: string = 'https://apps.apple.com/us/app/dice-id/id1548148979' +const AppleStoreLink: string = 'https://apps.apple.com/us/app/dice-id/id1624858853' interface DiceSetupModalProps { mutateMFAData: KeyedMutator onClose: () => void @@ -29,24 +28,7 @@ interface DiceSetupModalProps { const DiceSetupModal: FC = (props: DiceSetupModalProps) => { const [step, setStep]: [number, Dispatch>] = useState(1) - const [diceConnectionId, setDiceConnectionId]: [ - number | undefined, - Dispatch> - ] = useState() - - const diceConnection: DiceConnectionStatus | undefined = useDiceIdConnection(props.profile.userId, diceConnectionId) - - const [isVerificationProcessing, setIsVerificationProcessing]: [boolean, Dispatch>] - = useState(false) - - useEffect(() => { - if (diceConnection && !diceConnectionId) { - setDiceConnectionId(diceConnection.id) - } - }, [ - diceConnection, - diceConnectionId, - ]) + const [diceConnectionUrl, setDiceConnectionUrl] = useState() function handleSecondaryButtonClick(): void { switch (step) { @@ -58,42 +40,25 @@ const DiceSetupModal: FC = (props: DiceSetupModalProps) => function handlePrimaryButtonClick(): void { switch (step) { case 1: - case 2: return setStep(step + 1) default: return props.onClose() } } - function verificationCallback(data: any): void { - if (data.success) { - const userEmail: string = get(data, 'user.profile.Email') - if (!isUndefined(userEmail) && lowerCase(userEmail) === lowerCase(props.profile.email)) { - updateMemberMFAStatusAsync(props.profile.userId, { - param: { - diceEnabled: true, - }, - }) - .then(() => { - props.mutateMFAData() - setStep(4) - // eslint-disable-next-line max-len - toast.success('Your credentials have been verified and you are all set for MFA using your decentralized identity (DICE ID).') - }) - .catch(() => { - toast.error('Something went wrong. Please try again later.') - }) - } else { - setStep(5) - } - } else { - setStep(5) + function handleDiceConnectionStatusChange(newStatus: DiceConnectionStatus): void { + if (newStatus.diceEnabled) { + setStep(4) + toast.success('Your credentials have been verified and you are all set for' + + ' MFA using your decentralized identity (DICE ID).') + props.mutateMFAData() + } else if (newStatus.accepted) { + setStep(3) + } else if (newStatus.connection) { + setDiceConnectionUrl(newStatus.connection) + setStep(2) } } - function onStartProcessing(): void { - setIsVerificationProcessing(true) - } - return ( = (props: DiceSetupModalProps) => onClick={handleSecondaryButtonClick} /> { - step !== 3 && ( + (step === 1 || step === 4) && (