From c4b482969493c6f5e4c92f1c6720de63007e4183 Mon Sep 17 00:00:00 2001 From: seunghyunOh Date: Sun, 11 Dec 2022 15:07:53 +0900 Subject: [PATCH] Linting --- backend/src/controllers/authController.ts | 310 +++++++++--------- backend/src/routes/auth.ts | 32 +- frontend/components/RouteGuard.js | 28 +- frontend/components/basic/InputField.tsx | 26 +- .../basic/table/ServiceTokenTable.js | 12 +- frontend/components/basic/table/UserTable.js | 76 ++--- .../dashboard/DashboardInputField.tsx | 34 +- frontend/components/dashboard/DropZone.tsx | 34 +- .../components/navigation/NavBarDashboard.tsx | 77 ++--- frontend/components/utilities/attemptLogin.js | 72 ++-- frontend/pages/api/auth/CheckAuth.ts | 2 +- frontend/pages/api/auth/Logout.ts | 26 +- frontend/pages/api/files/GetSecrets.ts | 2 +- frontend/pages/api/organization/GetOrg.ts | 14 +- .../pages/api/organization/GetOrgUsers.ts | 19 +- frontend/pages/api/organization/getOrgs.ts | 12 +- frontend/pages/api/user/getUser.ts | 12 +- .../pages/api/workspace/createWorkspace.ts | 22 +- .../pages/api/workspace/getLatestFileKey.ts | 19 +- .../pages/api/workspace/getProjectInfo.ts | 19 +- .../pages/api/workspace/getWorkspaceUsers.ts | 14 +- frontend/pages/api/workspace/getWorkspaces.ts | 12 +- frontend/pages/dashboard/[id].js | 144 ++++---- frontend/pages/integrations/[id].js | 143 ++++---- frontend/pages/settings/org/[id].js | 92 +++--- frontend/pages/signup.tsx | 164 ++++----- frontend/pages/users/[id].js | 68 ++-- 27 files changed, 745 insertions(+), 740 deletions(-) diff --git a/backend/src/controllers/authController.ts b/backend/src/controllers/authController.ts index 9fbd58e93..eb537f2b9 100644 --- a/backend/src/controllers/authController.ts +++ b/backend/src/controllers/authController.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ import { Request, Response } from 'express'; import jwt from 'jsonwebtoken'; import * as Sentry from '@sentry/node'; @@ -5,17 +6,17 @@ import * as bigintConversion from 'bigint-conversion'; const jsrp = require('jsrp'); import { User } from '../models'; import { createToken, issueTokens, clearTokens } from '../helpers/auth'; -import { - NODE_ENV, - JWT_AUTH_LIFETIME, - JWT_AUTH_SECRET, - JWT_REFRESH_SECRET +import { + NODE_ENV, + JWT_AUTH_LIFETIME, + JWT_AUTH_SECRET, + JWT_REFRESH_SECRET } from '../config'; declare module 'jsonwebtoken' { - export interface UserIDJwtPayload extends jwt.JwtPayload { - userId: string; - } + export interface UserIDJwtPayload extends jwt.JwtPayload { + userId: string; + } } const clientPublicKeys: any = {}; @@ -27,47 +28,45 @@ const clientPublicKeys: any = {}; * @returns */ export const login1 = async (req: Request, res: Response) => { - try { - const { - email, - clientPublicKey - }: { email: string; clientPublicKey: string } = req.body; - - const user = await User.findOne({ - email - }).select('+salt +verifier'); - + try { + const { + email, + clientPublicKey + }: { email: string; clientPublicKey: string } = req.body; - if (!user) throw new Error('Failed to find user'); + const user = await User.findOne({ + email + }).select('+salt +verifier'); - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier - }, - () => { - // generate server-side public key - const serverPublicKey = server.getPublicKey(); - clientPublicKeys[email] = { - clientPublicKey, - serverBInt: bigintConversion.bigintToBuf(server.bInt) - }; - + if (!user) throw new Error('Failed to find user'); - return res.status(200).send({ - serverPublicKey, - salt: user.salt - }); - } - ); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to start authentication process' - }); - } + const server = new jsrp.server(); + server.init( + { + salt: user.salt, + verifier: user.verifier + }, + () => { + // generate server-side public key + const serverPublicKey = server.getPublicKey(); + clientPublicKeys[email] = { + clientPublicKey, + serverBInt: bigintConversion.bigintToBuf(server.bInt) + }; + + return res.status(200).send({ + serverPublicKey, + salt: user.salt + }); + } + ); + } catch (err) { + Sentry.setUser(null); + Sentry.captureException(err); + return res.status(400).send({ + message: 'Failed to start authentication process' + }); + } }; /** @@ -78,59 +77,59 @@ export const login1 = async (req: Request, res: Response) => { * @returns */ export const login2 = async (req: Request, res: Response) => { - try { - const { email, clientProof } = req.body; - const user = await User.findOne({ - email - }).select('+salt +verifier +publicKey +encryptedPrivateKey +iv +tag'); + try { + const { email, clientProof } = req.body; + const user = await User.findOne({ + email + }).select('+salt +verifier +publicKey +encryptedPrivateKey +iv +tag'); - if (!user) throw new Error('Failed to find user'); + if (!user) throw new Error('Failed to find user'); - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier, - b: clientPublicKeys[email].serverBInt - }, - async () => { - server.setClientPublicKey(clientPublicKeys[email].clientPublicKey); + const server = new jsrp.server(); + server.init( + { + salt: user.salt, + verifier: user.verifier, + b: clientPublicKeys[email].serverBInt + }, + async () => { + server.setClientPublicKey(clientPublicKeys[email].clientPublicKey); - // compare server and client shared keys - if (server.checkClientProof(clientProof)) { - // issue tokens - const tokens = await issueTokens({ userId: user._id.toString() }); - - // store (refresh) token in httpOnly cookie - res.cookie('jid', tokens.refreshToken, { - httpOnly: true, - path: '/token', - sameSite: "strict", - secure: NODE_ENV === 'production' ? true : false - }); + // compare server and client shared keys + if (server.checkClientProof(clientProof)) { + // issue tokens + const tokens = await issueTokens({ userId: user._id.toString() }); - // return (access) token in response - return res.status(200).send({ - token: tokens.token, - publicKey: user.publicKey, - encryptedPrivateKey: user.encryptedPrivateKey, - iv: user.iv, - tag: user.tag - }); - } + // store (refresh) token in httpOnly cookie + res.cookie('jid', tokens.refreshToken, { + httpOnly: true, + path: '/token', + sameSite: 'strict', + secure: NODE_ENV === 'production' ? true : false + }); - return res.status(400).send({ - message: 'Failed to authenticate. Try again?' - }); - } - ); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to authenticate. Try again?' - }); - } + // return (access) token in response + return res.status(200).send({ + token: tokens.token, + publicKey: user.publicKey, + encryptedPrivateKey: user.encryptedPrivateKey, + iv: user.iv, + tag: user.tag + }); + } + + return res.status(400).send({ + message: 'Failed to authenticate. Try again?' + }); + } + ); + } catch (err) { + Sentry.setUser(null); + Sentry.captureException(err); + return res.status(400).send({ + message: 'Failed to authenticate. Try again?' + }); + } }; /** @@ -140,29 +139,29 @@ export const login2 = async (req: Request, res: Response) => { * @returns */ export const logout = async (req: Request, res: Response) => { - try { - await clearTokens({ - userId: req.user._id.toString() - }); - - // clear httpOnly cookie - res.cookie('jid', '', { - httpOnly: true, - path: '/token', - sameSite: "strict", - secure: NODE_ENV === 'production' ? true : false - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to logout' - }); - } + try { + await clearTokens({ + userId: req.user._id.toString() + }); - return res.status(200).send({ - message: 'Successfully logged out.' - }); + // clear httpOnly cookie + res.cookie('jid', '', { + httpOnly: true, + path: '/token', + sameSite: 'strict', + secure: NODE_ENV === 'production' ? true : false + }); + } catch (err) { + Sentry.setUser({ email: req.user.email }); + Sentry.captureException(err); + return res.status(400).send({ + message: 'Failed to logout' + }); + } + + return res.status(200).send({ + message: 'Successfully logged out.' + }); }; /** @@ -172,9 +171,9 @@ export const logout = async (req: Request, res: Response) => { * @returns */ export const checkAuth = async (req: Request, res: Response) => - res.status(200).send({ - message: 'Authenticated' - }); + res.status(200).send({ + message: 'Authenticated' + }); /** * Return new token by redeeming refresh token @@ -183,42 +182,41 @@ export const checkAuth = async (req: Request, res: Response) => * @returns */ export const getNewToken = async (req: Request, res: Response) => { - try { - const refreshToken = req.cookies.jid; - - if (!refreshToken) { - throw new Error('Failed to find token in request cookies'); - } - - const decodedToken = ( - jwt.verify(refreshToken, JWT_REFRESH_SECRET) - ); - - const user = await User.findOne({ - _id: decodedToken.userId - }).select('+publicKey'); + try { + const refreshToken = req.cookies.jid; - if (!user) throw new Error('Failed to authenticate unfound user'); - if (!user?.publicKey) - throw new Error('Failed to authenticate not fully set up account'); - - const token = createToken({ - payload: { - userId: decodedToken.userId - }, - expiresIn: JWT_AUTH_LIFETIME, - secret: JWT_AUTH_SECRET - }); - - return res.status(200).send({ - token - }); - - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Invalid request' - }); - } + if (!refreshToken) { + throw new Error('Failed to find token in request cookies'); + } + + const decodedToken = ( + jwt.verify(refreshToken, JWT_REFRESH_SECRET) + ); + + const user = await User.findOne({ + _id: decodedToken.userId + }).select('+publicKey'); + + if (!user) throw new Error('Failed to authenticate unfound user'); + if (!user?.publicKey) + throw new Error('Failed to authenticate not fully set up account'); + + const token = createToken({ + payload: { + userId: decodedToken.userId + }, + expiresIn: JWT_AUTH_LIFETIME, + secret: JWT_AUTH_SECRET + }); + + return res.status(200).send({ + token + }); + } catch (err) { + Sentry.setUser(null); + Sentry.captureException(err); + return res.status(400).send({ + message: 'Invalid request' + }); + } }; diff --git a/backend/src/routes/auth.ts b/backend/src/routes/auth.ts index 43a57fe7e..6be9c09f7 100644 --- a/backend/src/routes/auth.ts +++ b/backend/src/routes/auth.ts @@ -5,28 +5,24 @@ import { requireAuth, validateRequest } from '../middleware'; import { authController } from '../controllers'; import { loginLimiter } from '../helpers/rateLimiter'; +router.post('/token', validateRequest, authController.getNewToken); + router.post( - '/token', - validateRequest, - authController.getNewToken + '/login1', + loginLimiter, + body('email').exists().trim().notEmpty(), + body('clientPublicKey').exists().trim().notEmpty(), + validateRequest, + authController.login1 ); router.post( - '/login1', - loginLimiter, - body('email').exists().trim().notEmpty(), - body('clientPublicKey').exists().trim().notEmpty(), - validateRequest, - authController.login1 -); - -router.post( - '/login2', - loginLimiter, - body('email').exists().trim().notEmpty(), - body('clientProof').exists().trim().notEmpty(), - validateRequest, - authController.login2 + '/login2', + loginLimiter, + body('email').exists().trim().notEmpty(), + body('clientProof').exists().trim().notEmpty(), + validateRequest, + authController.login2 ); router.post('/logout', requireAuth, authController.logout); diff --git a/frontend/components/RouteGuard.js b/frontend/components/RouteGuard.js index a21c0c86a..d08972b99 100644 --- a/frontend/components/RouteGuard.js +++ b/frontend/components/RouteGuard.js @@ -1,9 +1,9 @@ -import { useEffect, useState } from "react"; -import Image from "next/image"; -import { useRouter } from "next/router"; +import { useEffect, useState } from 'react'; +import Image from 'next/image'; +import { useRouter } from 'next/router'; -import { publicPaths } from "~/const"; -import checkAuth from "~/pages/api/auth/CheckAuth"; +import { publicPaths } from '~/const'; +import checkAuth from '~/pages/api/auth/CheckAuth'; // #TODO: finish spinner only when the data loads fully // #TODO: Redirect somewhere if the page does not exist @@ -22,16 +22,16 @@ export default function RouteGuard({ children }) { // #TODO: add the loading page when not yet authorized. const hideContent = () => setAuthorized(false); // const onError = () => setAuthorized(true) - router.events.on("routeChangeStart", hideContent); + router.events.on('routeChangeStart', hideContent); // router.events.on("routeChangeError", onError); // on route change complete - run auth check - router.events.on("routeChangeComplete", authCheck); + router.events.on('routeChangeComplete', authCheck); // unsubscribe from events in useEffect return function return () => { - router.events.off("routeChangeStart", hideContent); - router.events.off("routeChangeComplete", authCheck); + router.events.off('routeChangeStart', hideContent); + router.events.off('routeChangeComplete', authCheck); // router.events.off("routeChangeError", onError); }; // eslint-disable-next-line react-hooks/exhaustive-deps @@ -43,7 +43,7 @@ export default function RouteGuard({ children }) { */ async function authCheck(url) { // Make sure that we don't redirect when the user is on the following pages. - const path = "/" + url.split("?")[0].split("/")[1]; + const path = '/' + url.split('?')[0].split('/')[1]; // Check if the user is authenticated const response = await checkAuth(); @@ -51,16 +51,16 @@ export default function RouteGuard({ children }) { if (!publicPaths.includes(path)) { try { if (response.status !== 200) { - router.push("/login"); - console.log("Unauthorized to access."); + router.push('/login'); + console.log('Unauthorized to access.'); setAuthorized(false); } else { setAuthorized(true); - console.log("Authorized to access."); + console.log('Authorized to access.'); } } catch (error) { console.log( - "Error (probably the authCheck route is stuck again...):", + 'Error (probably the authCheck route is stuck again...):', error ); } diff --git a/frontend/components/basic/InputField.tsx b/frontend/components/basic/InputField.tsx index 139304ea6..141578214 100644 --- a/frontend/components/basic/InputField.tsx +++ b/frontend/components/basic/InputField.tsx @@ -1,9 +1,9 @@ -import React, { useState } from "react"; -import { useRouter } from "next/router"; -import { faCircle, faEye, faEyeSlash } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import React, { useState } from 'react'; +import { useRouter } from 'next/router'; +import { faCircle, faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import guidGenerator from "../utilities/randomId"; +import guidGenerator from '../utilities/randomId'; interface InputFieldProps { static?: boolean; @@ -23,7 +23,7 @@ interface InputFieldProps { const InputField = ( props: InputFieldProps & - Pick + Pick ) => { const [passwordVisible, setPasswordVisible] = useState(false); const router = useRouter(); @@ -75,28 +75,28 @@ const InputField = (
props.onChangeHandler(e.target.value)} - type={passwordVisible === false ? props.type : "text"} + type={passwordVisible === false ? props.type : 'text'} placeholder={props.placeholder} value={props.value} required={props.isRequired} className={`${ props.blurred - ? "text-bunker-800 group-hover:text-gray-400 focus:text-gray-400 active:text-gray-400" - : "" + ? 'text-bunker-800 group-hover:text-gray-400 focus:text-gray-400 active:text-gray-400' + : '' } ${ - props.error ? "focus:ring-red/50" : "focus:ring-primary/50" + props.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`} name={props.name} spellCheck="false" autoComplete={props.autoComplete} id={props.id} /> - {props.label?.includes("Password") && ( + {props.label?.includes('Password') && (
)} - {row.status == "completed" && myUser !== row.email && ( + {row.status == 'completed' && myUser !== row.email && (
{myUser !== row.email && // row.role != "admin" && - myRole != "member" ? ( + myRole != 'member' ? (
)} - {!["Heroku"].includes(integrations[integration].name) && ( + {!['Heroku'].includes(integrations[integration].name) && (
Coming Soon @@ -351,7 +353,8 @@ export default function Integrations() {

Click on a framework to get the setup instructions.

-
+
+
{frameworks.map((framework) => (
-
1 ? "text-sm px-1" : "text-xl px-2"} text-center w-full max-w-xs`}> - {framework?.image && integration logo} - {framework?.name && framework?.image &&
} +
1 + ? 'text-sm px-1' + : 'text-xl px-2' + } text-center w-full max-w-xs`} + > + {framework?.image && ( + integration logo + )} + {framework?.name && framework?.image && ( +
+ )} {framework?.name && framework.name}
diff --git a/frontend/pages/settings/org/[id].js b/frontend/pages/settings/org/[id].js index ca765abe7..80f6efc5d 100644 --- a/frontend/pages/settings/org/[id].js +++ b/frontend/pages/settings/org/[id].js @@ -1,62 +1,62 @@ -import React, { useEffect, useState } from "react"; -import Head from "next/head"; -import { useRouter } from "next/router"; +import React, { useEffect, useState } from 'react'; +import Head from 'next/head'; +import { useRouter } from 'next/router'; import { faMagnifyingGlass, faPlus, - faX, -} from "@fortawesome/free-solid-svg-icons"; -import { faCheck } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + faX +} from '@fortawesome/free-solid-svg-icons'; +import { faCheck } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import Button from "~/components/basic/buttons/Button"; -import AddIncidentContactDialog from "~/components/basic/dialog/AddIncidentContactDialog"; -import AddUserDialog from "~/components/basic/dialog/AddUserDialog"; -import InputField from "~/components/basic/InputField"; -import UserTable from "~/components/basic/table/UserTable"; -import NavHeader from "~/components/navigation/NavHeader"; -import guidGenerator from "~/utilities/randomId"; +import Button from '~/components/basic/buttons/Button'; +import AddIncidentContactDialog from '~/components/basic/dialog/AddIncidentContactDialog'; +import AddUserDialog from '~/components/basic/dialog/AddUserDialog'; +import InputField from '~/components/basic/InputField'; +import UserTable from '~/components/basic/table/UserTable'; +import NavHeader from '~/components/navigation/NavHeader'; +import guidGenerator from '~/utilities/randomId'; -import addUserToOrg from "../../api/organization/addUserToOrg"; -import deleteIncidentContact from "../../api/organization/deleteIncidentContact"; -import getIncidentContacts from "../../api/organization/getIncidentContacts"; -import getOrganization from "../../api/organization/GetOrg"; -import getOrganizationSubscriptions from "../../api/organization/GetOrgSubscription"; -import getOrganizationUsers from "../../api/organization/GetOrgUsers"; -import renameOrg from "../../api/organization/renameOrg"; -import getUser from "../../api/user/getUser"; -import deleteWorkspace from "../../api/workspace/deleteWorkspace"; -import getWorkspaces from "../../api/workspace/getWorkspaces"; +import addUserToOrg from '../../api/organization/addUserToOrg'; +import deleteIncidentContact from '../../api/organization/deleteIncidentContact'; +import getIncidentContacts from '../../api/organization/getIncidentContacts'; +import getOrganization from '../../api/organization/GetOrg'; +import getOrganizationSubscriptions from '../../api/organization/GetOrgSubscription'; +import getOrganizationUsers from '../../api/organization/GetOrgUsers'; +import renameOrg from '../../api/organization/renameOrg'; +import getUser from '../../api/user/getUser'; +import deleteWorkspace from '../../api/workspace/deleteWorkspace'; +import getWorkspaces from '../../api/workspace/getWorkspaces'; export default function SettingsOrg() { const [buttonReady, setButtonReady] = useState(false); const router = useRouter(); - const [orgName, setOrgName] = useState(""); - const [emailUser, setEmailUser] = useState(""); - const [workspaceToBeDeletedName, setWorkspaceToBeDeletedName] = useState(""); - const [searchUsers, setSearchUsers] = useState(""); - const [workspaceId, setWorkspaceId] = useState(""); + const [orgName, setOrgName] = useState(''); + const [emailUser, setEmailUser] = useState(''); + const [workspaceToBeDeletedName, setWorkspaceToBeDeletedName] = useState(''); + const [searchUsers, setSearchUsers] = useState(''); + const [workspaceId, setWorkspaceId] = useState(''); const [isAddIncidentContactOpen, setIsAddIncidentContactOpen] = useState(false); const [isAddUserOpen, setIsAddUserOpen] = useState( - router.asPath.split("?")[1] == "invite" + router.asPath.split('?')[1] == 'invite' ); const [incidentContacts, setIncidentContacts] = useState([]); - const [searchIncidentContact, setSearchIncidentContact] = useState(""); + const [searchIncidentContact, setSearchIncidentContact] = useState(''); const [userList, setUserList] = useState(); - const [personalEmail, setPersonalEmail] = useState(""); + const [personalEmail, setPersonalEmail] = useState(''); let workspaceIdTemp; - const [email, setEmail] = useState(""); - const [currentPlan, setCurrentPlan] = useState(""); + const [email, setEmail] = useState(''); + const [currentPlan, setCurrentPlan] = useState(''); useEffect(async () => { let org = await getOrganization({ - orgId: localStorage.getItem("orgData.id"), + orgId: localStorage.getItem('orgData.id') }); let orgData = org; setOrgName(orgData.name); let incidentContactsData = await getIncidentContacts( - localStorage.getItem("orgData.id") + localStorage.getItem('orgData.id') ); setIncidentContacts(incidentContactsData?.map((contact) => contact.email)); @@ -66,7 +66,7 @@ export default function SettingsOrg() { workspaceIdTemp = router.query.id; let orgUsers = await getOrganizationUsers({ - orgId: localStorage.getItem("orgData.id"), + orgId: localStorage.getItem('orgData.id') }); setUserList( orgUsers.map((user) => ({ @@ -78,11 +78,11 @@ export default function SettingsOrg() { status: user?.status, userId: user.user?._id, membershipId: user._id, - publicKey: user.user?.publicKey, + publicKey: user.user?.publicKey })) ); const subscriptions = await getOrganizationSubscriptions({ - orgId: localStorage.getItem("orgData.id"), + orgId: localStorage.getItem('orgData.id') }); setCurrentPlan(subscriptions.data[0].plan.product); }, []); @@ -93,7 +93,7 @@ export default function SettingsOrg() { }; const submitChanges = (newOrgName) => { - renameOrg(localStorage.getItem("orgData.id"), newOrgName); + renameOrg(localStorage.getItem('orgData.id'), newOrgName); setButtonReady(false); }; @@ -118,8 +118,8 @@ export default function SettingsOrg() { } async function submitAddUserModal(email) { - await addUserToOrg(email, localStorage.getItem("orgData.id")); - setEmail(""); + await addUserToOrg(email, localStorage.getItem('orgData.id')); + setEmail(''); setIsAddUserOpen(false); router.reload(); } @@ -128,7 +128,7 @@ export default function SettingsOrg() { setIncidentContacts( incidentContacts.filter((contact) => contact != incidentContact) ); - deleteIncidentContact(localStorage.getItem("orgData.id"), incidentContact); + deleteIncidentContact(localStorage.getItem('orgData.id'), incidentContact); }; /** @@ -148,7 +148,7 @@ export default function SettingsOrg() { ) { await deleteWorkspace(router.query.id); let userWorkspaces = await getWorkspaces(); - router.push("/dashboard/" + userWorkspaces[0]._id); + router.push('/dashboard/' + userWorkspaces[0]._id); } } }; @@ -241,7 +241,7 @@ export default function SettingsOrg() { className="pl-2 text-gray-400 rounded-r-md bg-white/5 w-full h-full outline-none" value={searchUsers} onChange={(e) => setSearchUsers(e.target.value)} - placeholder={"Search members..."} + placeholder={'Search members...'} />
@@ -302,7 +302,7 @@ export default function SettingsOrg() { className="pl-2 text-gray-400 rounded-tr-md bg-white/5 w-full h-full outline-none" value={searchIncidentContact} onChange={(e) => setSearchIncidentContact(e.target.value)} - placeholder={"Search..."} + placeholder={'Search...'} />
{incidentContacts?.filter((email) => diff --git a/frontend/pages/signup.tsx b/frontend/pages/signup.tsx index 9486191f7..77015ab75 100644 --- a/frontend/pages/signup.tsx +++ b/frontend/pages/signup.tsx @@ -1,72 +1,72 @@ -import React, { useEffect, useRef, useState } from "react"; -import ReactCodeInput from "react-code-input"; -import dynamic from "next/dynamic"; -import Head from "next/head"; -import Image from "next/image"; -import Link from "next/link"; -import { useRouter } from "next/router"; -import { faCheck, faWarning, faX } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import React, { useEffect, useRef, useState } from 'react'; +import ReactCodeInput from 'react-code-input'; +import dynamic from 'next/dynamic'; +import Head from 'next/head'; +import Image from 'next/image'; +import Link from 'next/link'; +import { useRouter } from 'next/router'; +import { faCheck, faWarning, faX } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import Button from "~/components/basic/buttons/Button"; -import Error from "~/components/basic/Error"; -import InputField from "~/components/basic/InputField"; -import Aes256Gcm from "~/components/utilities/cryptography/aes-256-gcm"; -import issueBackupKey from "~/components/utilities/cryptography/issueBackupKey"; -import attemptLogin from "~/utilities/attemptLogin"; -import passwordCheck from "~/utilities/checks/PasswordCheck"; +import Button from '~/components/basic/buttons/Button'; +import Error from '~/components/basic/Error'; +import InputField from '~/components/basic/InputField'; +import Aes256Gcm from '~/components/utilities/cryptography/aes-256-gcm'; +import issueBackupKey from '~/components/utilities/cryptography/issueBackupKey'; +import attemptLogin from '~/utilities/attemptLogin'; +import passwordCheck from '~/utilities/checks/PasswordCheck'; -import checkEmailVerificationCode from "./api/auth/CheckEmailVerificationCode"; -import completeAccountInformationSignup from "./api/auth/CompleteAccountInformationSignup"; -import sendVerificationEmail from "./api/auth/SendVerificationEmail"; -import getWorkspaces from "./api/workspace/getWorkspaces"; +import checkEmailVerificationCode from './api/auth/CheckEmailVerificationCode'; +import completeAccountInformationSignup from './api/auth/CompleteAccountInformationSignup'; +import sendVerificationEmail from './api/auth/SendVerificationEmail'; +import getWorkspaces from './api/workspace/getWorkspaces'; // const ReactCodeInput = dynamic(import("react-code-input")); -const nacl = require("tweetnacl"); -const jsrp = require("jsrp"); -nacl.util = require("tweetnacl-util"); +const nacl = require('tweetnacl'); +const jsrp = require('jsrp'); +nacl.util = require('tweetnacl-util'); const client = new jsrp.client(); // The stye for the verification code input const props = { inputStyle: { - fontFamily: "monospace", - margin: "4px", - MozAppearance: "textfield", - width: "55px", - borderRadius: "5px", - fontSize: "24px", - height: "55px", - paddingLeft: "7", - backgroundColor: "#0d1117", - color: "white", - border: "1px solid gray", - textAlign: "center", - }, + fontFamily: 'monospace', + margin: '4px', + MozAppearance: 'textfield', + width: '55px', + borderRadius: '5px', + fontSize: '24px', + height: '55px', + paddingLeft: '7', + backgroundColor: '#0d1117', + color: 'white', + border: '1px solid gray', + textAlign: 'center' + } } as const; const propsPhone = { inputStyle: { - fontFamily: "monospace", - margin: "4px", - MozAppearance: "textfield", - width: "40px", - borderRadius: "5px", - fontSize: "24px", - height: "40px", - paddingLeft: "7", - backgroundColor: "#0d1117", - color: "white", - border: "1px solid gray", - textAlign: "center", - }, + fontFamily: 'monospace', + margin: '4px', + MozAppearance: 'textfield', + width: '40px', + borderRadius: '5px', + fontSize: '24px', + height: '40px', + paddingLeft: '7', + backgroundColor: '#0d1117', + color: 'white', + border: '1px solid gray', + textAlign: 'center' + } } as const; export default function SignUp() { - const [email, setEmail] = useState(""); - const [password, setPassword] = useState(""); - const [firstName, setFirstName] = useState(""); - const [lastName, setLastName] = useState(""); - const [code, setCode] = useState(""); + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [firstName, setFirstName] = useState(''); + const [lastName, setLastName] = useState(''); + const [code, setCode] = useState(''); const [codeError, setCodeError] = useState(false); const [firstNameError, setFirstNameError] = useState(false); const [lastNameError, setLastNameError] = useState(false); @@ -77,22 +77,22 @@ export default function SignUp() { const [passwordErrorSpecialChar, setPasswordErrorSpecialChar] = useState(false); const [emailError, setEmailError] = useState(false); - const [emailErrorMessage, setEmailErrorMessage] = useState(""); + const [emailErrorMessage, setEmailErrorMessage] = useState(''); const [step, setStep] = useState(1); const router = useRouter(); const [errorLogin, setErrorLogin] = useState(false); const [isLoading, setIsLoading] = useState(false); const [backupKeyError, setBackupKeyError] = useState(false); - const [verificationToken, setVerificationToken] = useState(); + const [verificationToken, setVerificationToken] = useState(''); const [backupKeyIssued, setBackupKeyIssued] = useState(false); useEffect(() => { const tryAuth = async () => { try { const userWorkspaces = await getWorkspaces(); - router.push("/dashboard/" + userWorkspaces[0]._id); + router.push('/dashboard/' + userWorkspaces[0]._id); } catch (error) { - console.log("Error - Not logged in yet"); + console.log('Error - Not logged in yet'); } }; tryAuth(); @@ -109,8 +109,8 @@ export default function SignUp() { setStep(2); } else if (step == 2) { // Checking if the code matches the email. - const response = await checkEmailVerificationCode(email, code); - if (response.status === 200 || code == "111222") { + const response = await checkEmailVerificationCode({ email, code }); + if (response.status === 200 || code == '111222') { setVerificationToken((await response.json()).token); setStep(3); } else { @@ -128,15 +128,15 @@ export default function SignUp() { let emailCheckBool = false; if (!email) { setEmailError(true); - setEmailErrorMessage("Please enter your email."); + setEmailErrorMessage('Please enter your email.'); emailCheckBool = true; } else if ( - !email.includes("@") || - !email.includes(".") || + !email.includes('@') || + !email.includes('.') || !/[a-z]/.test(email) ) { setEmailError(true); - setEmailErrorMessage("Please enter a valid email."); + setEmailErrorMessage('Please enter a valid email.'); emailCheckBool = true; } else { setEmailError(false); @@ -170,7 +170,7 @@ export default function SignUp() { setPasswordErrorLength, setPasswordErrorNumber, setPasswordErrorLowerCase, - currentErrorCheck: errorCheck, + currentErrorCheck: errorCheck }); if (!errorCheck) { @@ -187,16 +187,16 @@ export default function SignUp() { .slice(0, 32) .padStart( 32 + (password.slice(0, 32).length - new Blob([password]).size), - "0" + '0' ) ) as { ciphertext: string; iv: string; tag: string }; - localStorage.setItem("PRIVATE_KEY", PRIVATE_KEY); + localStorage.setItem('PRIVATE_KEY', PRIVATE_KEY); client.init( { username: email, - password: password, + password: password }, async () => { client.createVerifier( @@ -212,17 +212,17 @@ export default function SignUp() { tag, salt: result.salt, verifier: result.verifier, - token: verificationToken, + token: verificationToken }); // if everything works, go the main dashboard page. if (response.status === 200) { // response = await response.json(); - localStorage.setItem("publicKey", PUBLIC_KEY); - localStorage.setItem("encryptedPrivateKey", ciphertext); - localStorage.setItem("iv", iv); - localStorage.setItem("tag", tag); + localStorage.setItem('publicKey', PUBLIC_KEY); + localStorage.setItem('encryptedPrivateKey', ciphertext); + localStorage.setItem('iv', iv); + localStorage.setItem('tag', tag); try { await attemptLogin( @@ -295,10 +295,10 @@ export default function SignUp() { const step2 = (

- {"We've"} sent a verification email to{" "} + {"We've"} sent a verification email to{' '}

- {email}{" "} + {email}{' '}

14 characters @@ -436,7 +436,7 @@ export default function SignUp() { )}
1 lowercase character @@ -456,7 +456,7 @@ export default function SignUp() { )}
1 number @@ -505,13 +505,13 @@ export default function SignUp() { await issueBackupKey({ email, password, - personalName: firstName + " " + lastName, + personalName: firstName + ' ' + lastName, setBackupKeyError, - setBackupKeyIssued, + setBackupKeyIssued }); const userWorkspaces = await getWorkspaces(); const userWorkspace = userWorkspaces[0]._id; - router.push("/home/" + userWorkspace); + router.push('/home/' + userWorkspace); }} size="lg" /> diff --git a/frontend/pages/users/[id].js b/frontend/pages/users/[id].js index de0307786..fe96ded3a 100644 --- a/frontend/pages/users/[id].js +++ b/frontend/pages/users/[id].js @@ -1,39 +1,39 @@ -import React, { useEffect, useState } from "react"; -import Head from "next/head"; -import Image from "next/image"; -import { useRouter } from "next/router"; -import { faMagnifyingGlass, faPlus } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import React, { useEffect, useState } from 'react'; +import Head from 'next/head'; +import Image from 'next/image'; +import { useRouter } from 'next/router'; +import { faMagnifyingGlass, faPlus } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import Button from "~/components/basic/buttons/Button"; -import AddProjectMemberDialog from "~/components/basic/dialog/AddProjectMemberDialog"; -import UserTable from "~/components/basic/table/UserTable"; -import NavHeader from "~/components/navigation/NavHeader"; -import guidGenerator from "~/utilities/randomId"; +import Button from '~/components/basic/buttons/Button'; +import AddProjectMemberDialog from '~/components/basic/dialog/AddProjectMemberDialog'; +import UserTable from '~/components/basic/table/UserTable'; +import NavHeader from '~/components/navigation/NavHeader'; +import guidGenerator from '~/utilities/randomId'; -import getOrganizationUsers from "../api/organization/GetOrgUsers"; -import getUser from "../api/user/getUser"; +import getOrganizationUsers from '../api/organization/GetOrgUsers'; +import getUser from '../api/user/getUser'; // import DeleteUserDialog from '~/components/basic/dialog/DeleteUserDialog'; -import addUserToWorkspace from "../api/workspace/addUserToWorkspace"; -import getWorkspaceUsers from "../api/workspace/getWorkspaceUsers"; -import uploadKeys from "../api/workspace/uploadKeys"; +import addUserToWorkspace from '../api/workspace/addUserToWorkspace'; +import getWorkspaceUsers from '../api/workspace/getWorkspaceUsers'; +import uploadKeys from '../api/workspace/uploadKeys'; // #TODO: Update all the workspaceIds -const crypto = require("crypto"); +const crypto = require('crypto'); const { decryptAssymmetric, - encryptAssymmetric, -} = require("../../components/utilities/cryptography/crypto"); -const nacl = require("tweetnacl"); -nacl.util = require("tweetnacl-util"); + encryptAssymmetric +} = require('../../components/utilities/cryptography/crypto'); +const nacl = require('tweetnacl'); +nacl.util = require('tweetnacl-util'); export default function Users() { let [isAddOpen, setIsAddOpen] = useState(false); // let [isDeleteOpen, setIsDeleteOpen] = useState(false); // let [userIdToBeDeleted, setUserIdToBeDeleted] = useState(false); - let [email, setEmail] = useState(""); - const [personalEmail, setPersonalEmail] = useState(""); - const [searchUsers, setSearchUsers] = useState(""); + let [email, setEmail] = useState(''); + const [personalEmail, setPersonalEmail] = useState(''); + const [searchUsers, setSearchUsers] = useState(''); const router = useRouter(); let workspaceId; @@ -57,25 +57,25 @@ export default function Users() { async function submitAddModal() { let result = await addUserToWorkspace(email, router.query.id); if (result?.invitee && result?.latestKey) { - const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY"); + const PRIVATE_KEY = localStorage.getItem('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: PRIVATE_KEY, + privateKey: PRIVATE_KEY }); const { ciphertext, nonce } = encryptAssymmetric({ plaintext: key, publicKey: result.invitee.publicKey, - privateKey: PRIVATE_KEY, + privateKey: PRIVATE_KEY }); uploadKeys(router.query.id, result.invitee._id, ciphertext, nonce); } - setEmail(""); + setEmail(''); setIsAddOpen(false); router.reload(); } @@ -93,7 +93,7 @@ export default function Users() { workspaceId = router.query.id; let workspaceUsers = await getWorkspaceUsers({ - workspaceId, + workspaceId }); const tempUserList = workspaceUsers.map((user) => ({ key: guidGenerator(), @@ -104,16 +104,16 @@ export default function Users() { status: user?.status, userId: user.user?._id, membershipId: user._id, - publicKey: user.user?.publicKey, + publicKey: user.user?.publicKey })); setUserList(tempUserList); const orgUsers = await getOrganizationUsers({ - orgId: localStorage.getItem("orgData.id"), + orgId: localStorage.getItem('orgData.id') }); setOrgUserList(orgUsers); setEmail( orgUsers - ?.filter((user) => user.status == "accepted") + ?.filter((user) => user.status == 'accepted') .map((user) => user.user.email) .filter( (email) => !tempUserList?.map((user1) => user1.email).includes(email) @@ -140,7 +140,7 @@ export default function Users() { submitModal={submitAddModal} email={email} data={orgUserList - ?.filter((user) => user.status == "accepted") + ?.filter((user) => user.status == 'accepted') .map((user) => user.user.email) .filter( (email) => !userList?.map((user1) => user1.email).includes(email) @@ -159,7 +159,7 @@ export default function Users() { className="pl-2 text-gray-400 rounded-r-md bg-white/5 w-full h-full outline-none" value={searchUsers} onChange={(e) => setSearchUsers(e.target.value)} - placeholder={"Search members..."} + placeholder={'Search members...'} />