/* eslint-disable no-nested-ternary */ /* eslint-disable no-unexpected-multiline */ /* eslint-disable react-hooks/exhaustive-deps */ import crypto from 'crypto'; import { useEffect, useMemo, useState } from 'react'; import Link from 'next/link'; import { useRouter } from 'next/router'; import { useTranslation } from 'next-i18next'; import { faBookOpen, faFileLines, faGear, faKey, faMobile, faPlug, faPlus, faUser } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import getOrganizations from '@app/pages/api/organization/getOrgs'; import getOrganizationUserProjects from '@app/pages/api/organization/GetOrgUserProjects'; import getOrganizationUsers from '@app/pages/api/organization/GetOrgUsers'; import getUser from '@app/pages/api/user/getUser'; import addUserToWorkspace from '@app/pages/api/workspace/addUserToWorkspace'; import createWorkspace from '@app/pages/api/workspace/createWorkspace'; import getWorkspaces from '@app/pages/api/workspace/getWorkspaces'; import uploadKeys from '@app/pages/api/workspace/uploadKeys'; import NavBarDashboard from '../navigation/NavBarDashboard'; import onboardingCheck from '../utilities/checks/OnboardingCheck'; import { tempLocalStorage } from '../utilities/checks/tempLocalStorage'; import { decryptAssymmetric, encryptAssymmetric } from '../utilities/cryptography/crypto'; import Button from './buttons/Button'; import AddWorkspaceDialog from './dialog/AddWorkspaceDialog'; import Listbox from './Listbox'; interface LayoutProps { children: React.ReactNode; } const Layout = ({ children }: LayoutProps) => { const router = useRouter(); const [workspaceMapping, setWorkspaceMapping] = useState[]>([]); const [workspaceSelected, setWorkspaceSelected] = useState('∞'); const [newWorkspaceName, setNewWorkspaceName] = useState(''); const [isOpen, setIsOpen] = useState(false); const [loading, setLoading] = useState(false); const [error, setError] = useState(false); const [totalOnboardingActionsDone, setTotalOnboardingActionsDone] = useState(0); const { t } = useTranslation(); const closeModal = () => { setIsOpen(false); }; const openModal = () => { setIsOpen(true); }; // TODO: what to do about the fact that 2ids can have the same name /** * When a user creates a new workspace, redirect them to the page of the new workspace. * @param {*} workspaceName */ const submitModal = async (workspaceName: string, addAllUsers: boolean) => { setLoading(true); // timeout code. setTimeout(() => setLoading(false), 1500); try { const workspaces = await getWorkspaces(); const currentWorkspaces = workspaces.map((workspace) => workspace.name); if (!currentWorkspaces.includes(workspaceName)) { const newWorkspace = await createWorkspace({ workspaceName, organizationId: tempLocalStorage('orgData.id') }); const newWorkspaceId = newWorkspace._id; const randomBytes = crypto.randomBytes(16).toString('hex'); const PRIVATE_KEY = String(localStorage.getItem('PRIVATE_KEY')); const myUser = await getUser(); const { ciphertext, nonce } = encryptAssymmetric({ plaintext: randomBytes, publicKey: myUser.publicKey, privateKey: PRIVATE_KEY }); await uploadKeys(newWorkspaceId, myUser._id, ciphertext, nonce); if (addAllUsers) { console.log('adding other users'); const orgUsers = await getOrganizationUsers({ orgId: tempLocalStorage('orgData.id') }); orgUsers.map(async (user: any) => { if (user.status === 'accepted' && user.email !== myUser.email) { const result = await addUserToWorkspace(user.user.email, newWorkspaceId); if (result?.invitee && result?.latestKey) { const TEMP_PRIVATE_KEY = tempLocalStorage('PRIVATE_KEY'); // assymmetrically decrypt symmetric key with local private key const key = decryptAssymmetric({ ciphertext: result.latestKey.encryptedKey, nonce: result.latestKey.nonce, publicKey: result.latestKey.sender.publicKey, privateKey: TEMP_PRIVATE_KEY }); const { ciphertext: inviteeCipherText, nonce: inviteeNonce } = encryptAssymmetric({ plaintext: key, publicKey: result.invitee.publicKey, privateKey: PRIVATE_KEY }); uploadKeys(newWorkspaceId, result.invitee._id, inviteeCipherText, inviteeNonce); } } }); } setWorkspaceMapping((prevState) => ({ ...prevState, [workspaceName]: newWorkspaceId })); setWorkspaceSelected(workspaceName); setIsOpen(false); setNewWorkspaceName(''); } else { console.error('A project with this name already exists.'); setError(true); setLoading(false); } } catch (err) { console.error(err); setError(true); setLoading(false); } }; const menuItems = useMemo( () => [ { href: `/dashboard/${workspaceMapping[workspaceSelected as any]}`, title: t('nav:menu.secrets'), emoji: }, { href: `/users/${workspaceMapping[workspaceSelected as any]}`, title: t('nav:menu.members'), emoji: }, { href: `/integrations/${workspaceMapping[workspaceSelected as any]}`, title: t('nav:menu.integrations'), emoji: }, { href: `/activity/${workspaceMapping[workspaceSelected as any]}`, title: 'Activity Logs', emoji: }, { href: `/settings/project/${workspaceMapping[workspaceSelected as any]}`, title: t('nav:menu.project-settings'), emoji: } ], [t, workspaceMapping, workspaceSelected] ); useEffect(() => { // Put a user in a workspace if they're not in one yet const putUserInWorkSpace = async () => { if (tempLocalStorage('orgData.id') === '') { const userOrgs = await getOrganizations(); localStorage.setItem('orgData.id', userOrgs[0]._id); } const orgUserProjects = await getOrganizationUserProjects({ orgId: tempLocalStorage('orgData.id') }); const userWorkspaces = orgUserProjects; if ( (userWorkspaces.length === 0 && router.asPath !== '/noprojects' && !router.asPath.includes('home') && !router.asPath.includes('settings')) || router.asPath === '/dashboard/undefined' ) { router.push('/noprojects'); } else if (router.asPath !== '/noprojects') { const intendedWorkspaceId = router.asPath .split('/') [router.asPath.split('/').length - 1].split('?')[0]; if (!['callback', 'create', 'authorize'].includes(intendedWorkspaceId)) { localStorage.setItem('projectData.id', intendedWorkspaceId); } // If a user is not a member of a workspace they are trying to access, just push them to one of theirs if ( !['callback', 'create', 'authorize'].includes(intendedWorkspaceId) && !userWorkspaces .map((workspace: { _id: string }) => workspace._id) .includes(intendedWorkspaceId) ) { router.push(`/dashboard/${userWorkspaces[0]._id}`); } else { setWorkspaceMapping( Object.fromEntries( userWorkspaces.map((workspace: any) => [workspace.name, workspace._id]) ) as any ); setWorkspaceSelected( Object.fromEntries( userWorkspaces.map((workspace: any) => [workspace._id, workspace.name]) )[router.asPath.split('/')[router.asPath.split('/').length - 1].split('?')[0]] ); } } }; putUserInWorkSpace(); onboardingCheck({ setTotalOnboardingActionsDone }); }, [router.query.id]); useEffect(() => { try { if ( workspaceMapping[workspaceSelected as any] && `${workspaceMapping[workspaceSelected as any]}` !== router.asPath.split('/')[router.asPath.split('/').length - 1].split('?')[0] ) { localStorage.setItem('projectData.id', `${workspaceMapping[workspaceSelected as any]}`); router.push(`/dashboard/${workspaceMapping[workspaceSelected as any]}`); } } catch (err) { console.log(err); } }, [workspaceSelected]); return ( <>
{children}

{` ${t('common:no-mobile')} `}

); }; export default Layout;