From 6cdbc834ab811df585c7d56df1a1adf9f423f265 Mon Sep 17 00:00:00 2001 From: Vladyslav Matsiiako Date: Sun, 4 Dec 2022 22:14:13 -0500 Subject: [PATCH 01/24] Tranforming more components to typescript (#47) --- frontend/.eslintrc | 7 ++- frontend/components/basic/buttons/Button.tsx | 10 ++-- frontend/components/basic/layout.js | 16 ++---- ...NavBarDashboard.js => NavBarDashboard.tsx} | 49 +++++++++++++------ .../{NavHeader.js => NavHeader.tsx} | 24 ++++++--- frontend/components/utilities/attemptLogin.js | 2 +- .../utilities/cryptography/changePassword.js | 6 +-- .../pages/api/auth/IssueBackupPrivateKey.js | 2 +- .../pages/api/auth/{Logout.js => Logout.ts} | 7 +-- .../api/organization/{GetOrg.js => GetOrg.ts} | 9 ++-- .../organization/{getOrgs.js => getOrgs.ts} | 6 +-- .../pages/api/user/{getUser.js => getUser.ts} | 7 +-- ...{getWorkspaceInfo.js => getProjectInfo.ts} | 11 ++--- frontend/pages/home/[id].tsx | 14 +++--- frontend/pages/signup.js | 2 +- frontend/pages/signupinvite.js | 4 +- 16 files changed, 93 insertions(+), 83 deletions(-) rename frontend/components/navigation/{NavBarDashboard.js => NavBarDashboard.tsx} (91%) rename frontend/components/navigation/{NavHeader.js => NavHeader.tsx} (69%) rename frontend/pages/api/auth/{Logout.js => Logout.ts} (89%) rename frontend/pages/api/organization/{GetOrg.js => GetOrg.ts} (65%) rename frontend/pages/api/organization/{getOrgs.js => getOrgs.ts} (81%) rename frontend/pages/api/user/{getUser.js => getUser.ts} (79%) rename frontend/pages/api/workspace/{getWorkspaceInfo.js => getProjectInfo.ts} (62%) diff --git a/frontend/.eslintrc b/frontend/.eslintrc index cfb3f694bb..b562aaa1fc 100644 --- a/frontend/.eslintrc +++ b/frontend/.eslintrc @@ -10,7 +10,12 @@ "rules": { "react-hooks/exhaustive-deps": "off", "no-unused-vars": "off", - "@typescript-eslint/no-unused-vars": "error", + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "simple-import-sort/exports": "warn", "simple-import-sort/imports": [ "warn", diff --git a/frontend/components/basic/buttons/Button.tsx b/frontend/components/basic/buttons/Button.tsx index 863dc4b48a..5fe2db803f 100644 --- a/frontend/components/basic/buttons/Button.tsx +++ b/frontend/components/basic/buttons/Button.tsx @@ -6,7 +6,7 @@ import { FontAwesomeIconProps, } from "@fortawesome/react-fontawesome"; -var classNames = require("classnames"); +const classNames = require("classnames"); type ButtonProps = { text: string; @@ -40,7 +40,7 @@ export default function Button(props: ButtonProps): JSX.Element { const activityStatus = props.active || (props.text != "" && props.textDisabled == undefined); - let styleButton = classNames( + const styleButton = classNames( "group m-auto md:m-0 inline-block rounded-md duration-200", // Setting background colors and hover modes @@ -67,7 +67,7 @@ export default function Button(props: ButtonProps): JSX.Element { props.size == "icon-sm" && "h-9 w-9 flex items-center justify-center" ); - let styleMainDiv = classNames( + const styleMainDiv = classNames( "relative font-medium flex items-center", // Setting the text color for the text and icon @@ -79,11 +79,11 @@ export default function Button(props: ButtonProps): JSX.Element { props.size == "icon" && "flex items-center justify-center" ); - let textStyle = classNames( + const textStyle = classNames( "relative duration-200", // Show the loading sign if the loading indicator is on - Boolean(props.loading) ? "opacity-0" : "opacity-100", + props.loading ? "opacity-0" : "opacity-100", props.size == "md" && "text-sm", props.size == "lg" && "text-lg" ); diff --git a/frontend/components/basic/layout.js b/frontend/components/basic/layout.js index 63dbf5dea5..6482c57acb 100644 --- a/frontend/components/basic/layout.js +++ b/frontend/components/basic/layout.js @@ -19,6 +19,7 @@ import getOrganizationUsers from "~/pages/api/organization/GetOrgUsers"; import addUserToWorkspace from "~/pages/api/workspace/addUserToWorkspace"; import createWorkspace from "~/pages/api/workspace/createWorkspace"; import getWorkspaces from "~/pages/api/workspace/getWorkspaces"; +import uploadKeys from "~/pages/api/workspace/uploadKeys"; import NavBarDashboard from "../navigation/NavBarDashboard"; import { @@ -156,9 +157,7 @@ export default function Layout({ children }) { router.push("/noprojects"); } else if (router.asPath != "/noprojects") { const intendedWorkspaceId = router.asPath - .split("/") - [router.asPath.split("/").length - 1].split("?")[0]; - + .split("/")[router.asPath.split("/").length - 1].split("?")[0]; // If a user is not a member of a workspace they are trying to access, just push them to one of theirs if ( intendedWorkspaceId != "heroku" && @@ -179,9 +178,7 @@ export default function Layout({ children }) { userWorkspaces.map((workspace) => [workspace._id, workspace.name]) )[ router.asPath - .split("/") - [router.asPath.split("/").length - 1].split("?")[0] - ] + .split("/")[router.asPath.split("/").length - 1].split("?")[0]] ); } } @@ -193,12 +190,9 @@ export default function Layout({ children }) { workspaceMapping[workspaceSelected] && workspaceMapping[workspaceSelected] !== router.asPath - .split("/") - [router.asPath.split("/").length - 1].split("?")[0] + .split("/")[router.asPath.split("/").length - 1].split("?")[0] ) { - router.push( - "/dashboard/" + workspaceMapping[workspaceSelected] + "?Development" - ); + router.push("/dashboard/" + workspaceMapping[workspaceSelected] + "?Development"); localStorage.setItem( "projectData.id", workspaceMapping[workspaceSelected] diff --git a/frontend/components/navigation/NavBarDashboard.js b/frontend/components/navigation/NavBarDashboard.tsx similarity index 91% rename from frontend/components/navigation/NavBarDashboard.js rename to frontend/components/navigation/NavBarDashboard.tsx index 80537dc1a1..5a6d63b8e0 100644 --- a/frontend/components/navigation/NavBarDashboard.js +++ b/frontend/components/navigation/NavBarDashboard.tsx @@ -47,27 +47,44 @@ const supportOptions = [ ], ]; -export default function Navbar({ onButtonPressed }) { +export interface ICurrentOrg { + name: string; +} + +export interface IUser { + firstName: string; + lastName: string; + email: string; +} + +/** + * This is the navigation bar in the main app. + * It has two main components: support options and user menu (inlcudes billing, logout, org/user settings) + * @returns NavBar + */ +export default function Navbar() { const router = useRouter(); - const [user, setUser] = useState({}); + const [user, setUser] = useState(); const [orgs, setOrgs] = useState([]); - const [currentOrg, setCurrentOrg] = useState([]); + const [currentOrg, setCurrentOrg] = useState(); - useEffect(async () => { - const userData = await getUser(); - setUser(userData); - const orgsData = await getOrganizations(); - setOrgs(orgsData); - const currentOrg = await getOrganization({ - orgId: localStorage.getItem("orgData.id"), - }); - setCurrentOrg(currentOrg); + useEffect(() => { + (async () => { + const userData = await getUser(); + setUser(userData); + const orgsData = await getOrganizations(); + setOrgs(orgsData); + const currentOrg = await getOrganization({ + orgId: String(localStorage.getItem("orgData.id")), + }); + setCurrentOrg(currentOrg); + })(); }, []); const closeApp = async () => { console.log("Logging out..."); await logout(); - router.push("/"); + router.push("/login"); }; return ( @@ -108,7 +125,7 @@ export default function Navbar({ onButtonPressed }) { key={guidGenerator()} target="_blank" rel="noopener" - href={option[2]} + href={String(option[2])} className="font-normal text-gray-300 duration-200 rounded-md w-full flex items-center py-0.5" >
@@ -238,9 +255,9 @@ export default function Navbar({ onButtonPressed }) {
{orgs .filter( - (org) => org._id != localStorage.getItem("orgData.id") + (org : { _id: string }) => org._id != localStorage.getItem("orgData.id") ) - .map((org) => ( + .map((org : { _id: string; name: string; }) => (
{ diff --git a/frontend/components/navigation/NavHeader.js b/frontend/components/navigation/NavHeader.tsx similarity index 69% rename from frontend/components/navigation/NavHeader.js rename to frontend/components/navigation/NavHeader.tsx index 3f65a5aa62..d6d8713ba6 100644 --- a/frontend/components/navigation/NavHeader.js +++ b/frontend/components/navigation/NavHeader.tsx @@ -1,29 +1,37 @@ import React, { useEffect, useState } from "react"; import { useRouter } from "next/router"; -import { faCcMastercard, faCcVisa } from "@fortawesome/free-brands-svg-icons"; import { faAngleRight, - faQuestionCircle, } from "@fortawesome/free-solid-svg-icons"; -import { faCircle } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import getOrganization from "~/pages/api/organization/GetOrg"; -import getWorkspaceInfo from "~/pages/api/workspace/getWorkspaceInfo"; +import getProjectInfo from "~/pages/api/workspace/getProjectInfo"; -export default function NavHeader({ pageName, isProjectRelated }) { +/** + * This is the component at the top of almost every page. + * It shows how to navigate to a certain page. + * It future these links should also be clickable and hoverable + * @param obj + * @param obj.pageName - Name of the page + * @param obj.isProjectRelated - whether this page is related to project or now (determine if it's 2 or 3 navigation steps) + * @returns + */ +export default function NavHeader({ pageName, isProjectRelated } : { pageName: string; isProjectRelated: boolean; }): JSX.Element { const [orgName, setOrgName] = useState(""); const [workspaceName, setWorkspaceName] = useState(""); const router = useRouter(); useEffect(() => { (async () => { + const orgId = localStorage.getItem("orgData.id") let org = await getOrganization({ - orgId: localStorage.getItem("orgData.id"), + orgId: orgId ? orgId : "", }); setOrgName(org.name); - let workspace = await getWorkspaceInfo({ - workspaceId: router.query.id, + + let workspace = await getProjectInfo({ + projectId: String(router.query.id), }); setWorkspaceName(workspace.name); })(); diff --git a/frontend/components/utilities/attemptLogin.js b/frontend/components/utilities/attemptLogin.js index c2e6bfc4b5..767fcb400d 100644 --- a/frontend/components/utilities/attemptLogin.js +++ b/frontend/components/utilities/attemptLogin.js @@ -43,7 +43,7 @@ const attemptLogin = async ( let serverPublicKey, salt; try { - const res = await login1(email, clientPublicKey); + let res = await login1(email, clientPublicKey); res = await res.json(); serverPublicKey = res.serverPublicKey; salt = res.salt; diff --git a/frontend/components/utilities/cryptography/changePassword.js b/frontend/components/utilities/cryptography/changePassword.js index 8bfaad6746..de0fd9c3a7 100644 --- a/frontend/components/utilities/cryptography/changePassword.js +++ b/frontend/components/utilities/cryptography/changePassword.js @@ -108,11 +108,7 @@ const changePassword = async ( } ); } catch (error) { - console.log( - "Something went wrong during changing the password", - slat, - serverPublicKey - ); + console.log("Something went wrong during changing the password"); } return true; }; diff --git a/frontend/pages/api/auth/IssueBackupPrivateKey.js b/frontend/pages/api/auth/IssueBackupPrivateKey.js index 43e9f64eef..9a31f7b008 100644 --- a/frontend/pages/api/auth/IssueBackupPrivateKey.js +++ b/frontend/pages/api/auth/IssueBackupPrivateKey.js @@ -31,8 +31,8 @@ const issueBackupPrivateKey = ({ if (res.status == 200) { return res; } else { - return res; console.log("Failed to issue the backup key"); + return res; } }); }; diff --git a/frontend/pages/api/auth/Logout.js b/frontend/pages/api/auth/Logout.ts similarity index 89% rename from frontend/pages/api/auth/Logout.js rename to frontend/pages/api/auth/Logout.ts index 24c338a275..4dbcb7bcaa 100644 --- a/frontend/pages/api/auth/Logout.js +++ b/frontend/pages/api/auth/Logout.ts @@ -3,11 +3,8 @@ import SecurityClient from "~/utilities/SecurityClient"; /** * This route logs the user out. Note: the user should authorized to do this. * We first try to log out - if the authorization fails (response.status = 401), we refetch the new token, and then retry - * @param {*} req - * @param {*} res - * @returns */ -const logout = async (req, res) => { +const logout = async () => { return SecurityClient.fetchCall("/api/v1/auth/logout", { method: "POST", headers: { @@ -15,7 +12,7 @@ const logout = async (req, res) => { }, credentials: "include", }).then((res) => { - if (res.status == 200) { + if (res?.status == 200) { SecurityClient.setToken(""); // Delete the cookie by not setting a value; Alternatively clear the local storage localStorage.setItem("publicKey", ""); diff --git a/frontend/pages/api/organization/GetOrg.js b/frontend/pages/api/organization/GetOrg.ts similarity index 65% rename from frontend/pages/api/organization/GetOrg.js rename to frontend/pages/api/organization/GetOrg.ts index 74782a564f..ecb07bd2d3 100644 --- a/frontend/pages/api/organization/GetOrg.js +++ b/frontend/pages/api/organization/GetOrg.ts @@ -2,18 +2,17 @@ import SecurityClient from "~/utilities/SecurityClient"; /** * This route lets us get info about a certain org - * @param {*} req - * @param {*} res + * @param {string} orgId - the organization ID * @returns */ -const getOrganization = (req, res) => { - return SecurityClient.fetchCall("/api/v1/organization/" + req.orgId, { +const getOrganization = ({ orgId }: { orgId: string; }) => { + return SecurityClient.fetchCall("/api/v1/organization/" + orgId, { method: "GET", headers: { "Content-Type": "application/json", }, }).then(async (res) => { - if (res.status == 200) { + if (res?.status == 200) { return (await res.json()).organization; } else { console.log("Failed to get org info"); diff --git a/frontend/pages/api/organization/getOrgs.js b/frontend/pages/api/organization/getOrgs.ts similarity index 81% rename from frontend/pages/api/organization/getOrgs.js rename to frontend/pages/api/organization/getOrgs.ts index 6720c22a9d..cc655642ff 100644 --- a/frontend/pages/api/organization/getOrgs.js +++ b/frontend/pages/api/organization/getOrgs.ts @@ -2,18 +2,16 @@ import SecurityClient from "~/utilities/SecurityClient"; /** * This route lets us get the all the orgs of a certain user. - * @param {*} req - * @param {*} res * @returns */ -const getOrganizations = (req, res) => { +const getOrganizations = () => { return SecurityClient.fetchCall("/api/v1/organization", { method: "GET", headers: { "Content-Type": "application/json", }, }).then(async (res) => { - if (res.status == 200) { + if (res?.status == 200) { return (await res.json()).organizations; } else { console.log("Failed to get orgs of a user"); diff --git a/frontend/pages/api/user/getUser.js b/frontend/pages/api/user/getUser.ts similarity index 79% rename from frontend/pages/api/user/getUser.js rename to frontend/pages/api/user/getUser.ts index 10ca0d5f80..4bfebc5fe4 100644 --- a/frontend/pages/api/user/getUser.js +++ b/frontend/pages/api/user/getUser.ts @@ -2,18 +2,15 @@ import SecurityClient from "~/utilities/SecurityClient"; /** * This route gets the information about a specific user. - * @param {*} req - * @param {*} res - * @returns */ -const getUser = (req, res) => { +const getUser = () => { return SecurityClient.fetchCall("/api/v1/user", { method: "GET", headers: { "Content-Type": "application/json", }, }).then(async (res) => { - if (res.status == 200) { + if (res?.status == 200) { return (await res.json()).user; } else { console.log("Failed to get user info"); diff --git a/frontend/pages/api/workspace/getWorkspaceInfo.js b/frontend/pages/api/workspace/getProjectInfo.ts similarity index 62% rename from frontend/pages/api/workspace/getWorkspaceInfo.js rename to frontend/pages/api/workspace/getProjectInfo.ts index 4266dbbaaf..c6eef9dcea 100644 --- a/frontend/pages/api/workspace/getWorkspaceInfo.js +++ b/frontend/pages/api/workspace/getProjectInfo.ts @@ -2,13 +2,12 @@ import SecurityClient from "~/utilities/SecurityClient"; /** * This route lets us get the information of a certain project. - * @param {*} req - * @param {*} res + * @param {*} projectId - project ID (we renamed workspaces to projects in the app) * @returns */ -const getWorkspaceInfo = (req, res) => { +const getProjectInfo = ({ projectId }: { projectId: string; }) => { return SecurityClient.fetchCall( - "/api/v1/workspace/" + req.workspaceId, + "/api/v1/workspace/" + projectId, { method: "GET", headers: { @@ -16,7 +15,7 @@ const getWorkspaceInfo = (req, res) => { }, } ).then(async (res) => { - if (res.status == 200) { + if (res?.status == 200) { return (await res.json()).workspace; } else { console.log("Failed to get project info"); @@ -24,4 +23,4 @@ const getWorkspaceInfo = (req, res) => { }); }; -export default getWorkspaceInfo; +export default getProjectInfo; diff --git a/frontend/pages/home/[id].tsx b/frontend/pages/home/[id].tsx index 5ee7e920b4..21f15fcc37 100644 --- a/frontend/pages/home/[id].tsx +++ b/frontend/pages/home/[id].tsx @@ -98,22 +98,22 @@ export default function Home() { useEffect(() => { const checkUserActionsFunction = async () => { - let userActionSlack = await checkUserAction({ + const userActionSlack = await checkUserAction({ action: "slack_cta_clicked", }); setHasUserClickedSlack(userActionSlack ? true : false); - let userActionIntro = await checkUserAction({ + const userActionIntro = await checkUserAction({ action: "intro_cta_clicked", }); setHasUserClickedIntro(userActionIntro ? true : false); - let userActionStar = await checkUserAction({ + const userActionStar = await checkUserAction({ action: "star_cta_clicked", }); setHasUserStarred(userActionStar ? true : false); - let orgId = localStorage.getItem("orgData.id"); + const orgId = localStorage.getItem("orgData.id"); const orgUsers = await getOrganizationUsers({ orgId: orgId ? orgId : "", }); @@ -123,9 +123,9 @@ export default function Home() { }, []); return ( -
-
-
Your quick start guide
+
+
+
Your quick start guide
Click on the items below and follow the instructions.
{learningItem({ text: "Get to know Infisical", subText: "", complete: hasUserClickedIntro, icon: faHandPeace, time: "3 min", userAction: "intro_cta_clicked", link: "https://www.youtube.com/watch?v=JS3OKYU2078" })} {learningItem({ text: "Add your secrets", subText: "Click to see example secrets, and add your own.", complete: false, icon: faPlus, time: "2 min", userAction: "first_time_secrets_pushed", link: "/dashboard/" + router.query.id })} diff --git a/frontend/pages/signup.js b/frontend/pages/signup.js index dfd497cd74..77c3c7ef46 100644 --- a/frontend/pages/signup.js +++ b/frontend/pages/signup.js @@ -197,7 +197,7 @@ export default function SignUp() { }, async () => { client.createVerifier(async (err, result) => { - const response = await completeAccountInformationSignup({ + let response = await completeAccountInformationSignup({ email, firstName, lastName, diff --git a/frontend/pages/signupinvite.js b/frontend/pages/signupinvite.js index 8e7f1d4a0d..15c5117395 100644 --- a/frontend/pages/signupinvite.js +++ b/frontend/pages/signupinvite.js @@ -92,7 +92,7 @@ export default function SignupInvite() { }, async () => { client.createVerifier(async (err, result) => { - const response = await completeAccountInformationSignupInvite({ + let response = await completeAccountInformationSignupInvite({ email, firstName, lastName, @@ -291,7 +291,7 @@ export default function SignupInvite() {
)}
-
+
) : router.asPath == "/noprojects" ? ( -
-

{emoji}

+
+

+ {emoji} +

{title}
) : ( @@ -262,7 +302,9 @@ export default function Layout({ children }) {
-

{emoji}

+

+ {emoji} +

{title}
@@ -277,15 +319,21 @@ export default function Layout({ children }) { className={`flex relative px-0.5 py-2.5 text-white text-sm rounded cursor-pointer bg-primary-50/10`} >
-

+

+ +

Infisical Guide
) : ( - +
-

+

+ +

Infisical Guide
@@ -305,7 +353,7 @@ export default function Layout({ children }) {
{children}
-
+
void, - data: string[], - text: string, - buttonAction: () => void, - width: string, +interface ListBoxProps { + selected: string; + onChange: () => void; + data: string[]; + text: string; + buttonAction: () => void; + isFull?: boolean; } /** @@ -35,14 +34,14 @@ export default function ListBox({ data, text, buttonAction, - width, -} : ListBoxProps): JSX.Element { + isFull, +}: ListBoxProps): JSX.Element { return (
diff --git a/frontend/components/basic/buttons/Button.tsx b/frontend/components/basic/buttons/Button.tsx index 5fe2db803f..9f8d481b4f 100644 --- a/frontend/components/basic/buttons/Button.tsx +++ b/frontend/components/basic/buttons/Button.tsx @@ -12,7 +12,7 @@ type ButtonProps = { text: string; onButtonPressed: () => void; loading?: boolean; - color: string; + color?: string; size: string; icon?: IconProp; active?: boolean; diff --git a/frontend/components/utilities/SecurityClient.js b/frontend/components/utilities/SecurityClient.js index f8be6a0e19..78eebdebef 100644 --- a/frontend/components/utilities/SecurityClient.js +++ b/frontend/components/utilities/SecurityClient.js @@ -3,7 +3,7 @@ import token from "~/pages/api/auth/Token"; export default class SecurityClient { static #token = ""; - contructor() {} + constructor() {} static setToken(token) { this.#token = token; diff --git a/frontend/components/utilities/attemptLogin.js b/frontend/components/utilities/attemptLogin.js index 767fcb400d..5f7b926dc6 100644 --- a/frontend/components/utilities/attemptLogin.js +++ b/frontend/components/utilities/attemptLogin.js @@ -32,7 +32,6 @@ const attemptLogin = async ( isLogin ) => { try { - let userWorkspace, userOrg; client.init( { username: email, @@ -140,14 +139,8 @@ const attemptLogin = async ( "mongodb+srv://${DB_USERNAME}:${DB_PASSWORD}@mongodb.net", "personal", ], - DB_USERNAME: [ - "user1234", - "personal", - ], - DB_PASSWORD: [ - "ah8jak3hk8dhiu4dw7whxwe1l", - "personal", - ], + DB_USERNAME: ["user1234", "personal"], + DB_PASSWORD: ["ah8jak3hk8dhiu4dw7whxwe1l", "personal"], TWILIO_AUTH_TOKEN: [ "hgSIwDAKvz8PJfkj6xkzYqzGmAP3HLuG", "shared", diff --git a/frontend/components/utilities/checks/PasswordCheck.js b/frontend/components/utilities/checks/PasswordCheck.ts similarity index 83% rename from frontend/components/utilities/checks/PasswordCheck.js rename to frontend/components/utilities/checks/PasswordCheck.ts index 448c2942e4..10240b7476 100644 --- a/frontend/components/utilities/checks/PasswordCheck.js +++ b/frontend/components/utilities/checks/PasswordCheck.ts @@ -1,18 +1,21 @@ +interface PasswordCheckProps { + password: string; + currentErrorCheck: boolean; + setPasswordErrorLength: (value: boolean) => void; + setPasswordErrorNumber: (value: boolean) => void; + setPasswordErrorLowerCase: (value: boolean) => void; +} + /** * This function checks a user password with respect to some criteria. - * @param {*} password - * @param {*} setPasswordError - * @param {*} setPasswordErrorMessage - * @param {*} currentErrorCheck - * @returns */ -const passwordCheck = ( +const passwordCheck = ({ password, setPasswordErrorLength, setPasswordErrorNumber, setPasswordErrorLowerCase, - currentErrorCheck -) => { + currentErrorCheck, +}: PasswordCheckProps) => { let errorCheck = currentErrorCheck; if (!password || password.length < 14) { setPasswordErrorLength(true); diff --git a/frontend/components/utilities/checks/tempLocalStorage.ts b/frontend/components/utilities/checks/tempLocalStorage.ts new file mode 100644 index 0000000000..85623a30a5 --- /dev/null +++ b/frontend/components/utilities/checks/tempLocalStorage.ts @@ -0,0 +1,11 @@ +// this function is temporary until. have to create error handling logic for localStorage and delete this. +export const tempLocalStorage = (key: string) => { + const value = localStorage.getItem(key); + + if (value === null || value === "") { + console.warn("No value found in localStorage for key"); + return ""; + } + + return value; +}; diff --git a/frontend/pages/_app.js b/frontend/pages/_app.js index 6ed9af0131..a243771af7 100644 --- a/frontend/pages/_app.js +++ b/frontend/pages/_app.js @@ -3,7 +3,7 @@ import { useRouter } from "next/router"; import { config } from "@fortawesome/fontawesome-svg-core"; import { initPostHog } from "~/components/analytics/posthog"; -import Layout from "~/components/basic/layout"; +import Layout from "~/components/basic/Layout"; import RouteGuard from "~/components/RouteGuard"; import { publicPaths } from "~/const"; import { ENV } from "~/utilities/config"; diff --git a/frontend/pages/api/organization/GetOrgUserProjects.js b/frontend/pages/api/organization/GetOrgUserProjects.js index c091934562..c2d751f64d 100644 --- a/frontend/pages/api/organization/GetOrgUserProjects.js +++ b/frontend/pages/api/organization/GetOrgUserProjects.js @@ -6,7 +6,7 @@ import SecurityClient from "~/utilities/SecurityClient"; * @param {*} res * @returns */ -const getOrganizationUserProjects = (req, res) => { +const getOrganizationUserProjects = (req) => { return SecurityClient.fetchCall( "/api/v1/organization/" + req.orgId + "/my-workspaces", { diff --git a/frontend/pages/api/workspace/getWorkspaces.ts b/frontend/pages/api/workspace/getWorkspaces.ts index 9427c03d00..619041fdeb 100644 --- a/frontend/pages/api/workspace/getWorkspaces.ts +++ b/frontend/pages/api/workspace/getWorkspaces.ts @@ -1,3 +1,5 @@ +import { Workspaces } from "types/workspaces"; + import SecurityClient from "~/utilities/SecurityClient"; /** @@ -12,10 +14,11 @@ const getWorkspaces = () => { }, }).then(async (res) => { if (res?.status == 200) { - return (await res.json()).workspaces; - } else { - console.log("Failed to get projects"); + const data = (await res.json()) as unknown as { workspaces: Workspaces }; + return data.workspaces; } + + throw new Error("Failed to get projects"); }); }; diff --git a/frontend/pages/signup.js b/frontend/pages/signup.tsx similarity index 88% rename from frontend/pages/signup.js rename to frontend/pages/signup.tsx index 77c3c7ef46..cdfb46665c 100644 --- a/frontend/pages/signup.js +++ b/frontend/pages/signup.tsx @@ -1,4 +1,5 @@ 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"; @@ -20,7 +21,7 @@ import completeAccountInformationSignup from "./api/auth/CompleteAccountInformat import sendVerificationEmail from "./api/auth/SendVerificationEmail"; import getWorkspaces from "./api/workspace/getWorkspaces"; -const ReactCodeInput = dynamic(import("react-code-input")); +// const ReactCodeInput = dynamic(import("react-code-input")); const nacl = require("tweetnacl"); const jsrp = require("jsrp"); nacl.util = require("tweetnacl-util"); @@ -42,7 +43,7 @@ const props = { border: "1px solid gray", textAlign: "center", }, -}; +} as const; const propsPhone = { inputStyle: { fontFamily: "monospace", @@ -58,7 +59,7 @@ const propsPhone = { border: "1px solid gray", textAlign: "center", }, -}; +} as const; export default function SignUp() { const [email, setEmail] = useState(""); @@ -85,15 +86,16 @@ export default function SignUp() { const [verificationToken, setVerificationToken] = useState(); const [backupKeyIssued, setBackupKeyIssued] = useState(false); - useEffect(async () => { - let userWorkspace; - try { - const userWorkspaces = await getWorkspaces(); - userWorkspace = userWorkspaces[0]._id; - router.push("/dashboard/" + userWorkspace); - } catch (error) { - console.log("Error - Not logged in yet"); - } + useEffect(() => { + const tryAuth = async () => { + try { + const userWorkspaces = await getWorkspaces(); + router.push("/dashboard/" + userWorkspaces[0]._id); + } catch (error) { + console.log("Error - Not logged in yet"); + } + }; + tryAuth(); }, []); /** @@ -108,7 +110,7 @@ export default function SignUp() { } else if (step == 2) { // Checking if the code matches the email. const response = await checkEmailVerificationCode(email, code); - if (response.status == "200" || code == "111222") { + if (response.status === 200 || code == "111222") { setVerificationToken((await response.json()).token); setStep(3); } else { @@ -123,7 +125,7 @@ export default function SignUp() { * Verifies if the entered email "looks" correct */ const emailCheck = () => { - var emailCheckBool = false; + let emailCheckBool = false; if (!email) { setEmailError(true); setEmailErrorMessage("Please enter your email."); @@ -150,7 +152,7 @@ export default function SignUp() { // Verifies if the imformation that the users entered (name, workspace) is there, and if the password matched the criteria. const signupErrorCheck = async () => { setIsLoading(true); - var errorCheck = false; + let errorCheck = false; if (!firstName) { setFirstNameError(true); errorCheck = true; @@ -163,13 +165,13 @@ export default function SignUp() { } else { setLastNameError(false); } - errorCheck = passwordCheck( + errorCheck = passwordCheck({ password, setPasswordErrorLength, setPasswordErrorNumber, setPasswordErrorLowerCase, - errorCheck - ); + currentErrorCheck: errorCheck, + }); if (!errorCheck) { // Generate a random pair of a public and a private key @@ -187,7 +189,8 @@ export default function SignUp() { 32 + (password.slice(0, 32).length - new Blob([password]).size), "0" ) - ); + ) as { ciphertext: string; iv: string; tag: string }; + localStorage.setItem("PRIVATE_KEY", PRIVATE_KEY); client.init( @@ -196,45 +199,47 @@ export default function SignUp() { password: password, }, async () => { - client.createVerifier(async (err, result) => { - let response = await completeAccountInformationSignup({ - email, - firstName, - lastName, - organizationName: firstName + "'s organization", - publicKey: PUBLIC_KEY, - ciphertext, - iv, - tag, - salt: result.salt, - verifier: result.verifier, - token: verificationToken, - }); + client.createVerifier( + async (err: any, result: { salt: string; verifier: string }) => { + const response = await completeAccountInformationSignup({ + email, + firstName, + lastName, + organizationName: firstName + "'s organization", + publicKey: PUBLIC_KEY, + ciphertext, + iv, + tag, + salt: result.salt, + verifier: result.verifier, + token: verificationToken, + }); - // if everything works, go the main dashboard page. - if (!errorCheck && response.status == "200") { - response = await response.json(); + // 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( - email, - password, - setErrorLogin, - router, - true, - false - ); - incrementStep(); - } catch (error) { - setIsLoading(false); + try { + await attemptLogin( + email, + password, + setErrorLogin, + router, + true, + false + ); + incrementStep(); + } catch (error) { + setIsLoading(false); + } } } - }); + ); } ); } else { @@ -296,6 +301,8 @@ export default function SignUp() {

{ + onChangeHandler={(password: string) => { setPassword(password); - passwordCheck( + passwordCheck({ password, setPasswordErrorLength, setPasswordErrorNumber, setPasswordErrorLowerCase, - false - ); + currentErrorCheck: false, + }); }} type="password" value={password} @@ -496,7 +505,7 @@ export default function SignUp() { setBackupKeyIssued, }); const userWorkspaces = await getWorkspaces(); - let userWorkspace = userWorkspaces[0]._id; + const userWorkspace = userWorkspaces[0]._id; router.push("/home/" + userWorkspace); }} size="lg" diff --git a/frontend/types/workspaces.d.ts b/frontend/types/workspaces.d.ts new file mode 100644 index 0000000000..7b6fab001c --- /dev/null +++ b/frontend/types/workspaces.d.ts @@ -0,0 +1,8 @@ +export interface WorkSpace { + __v: number; + _id: string; + name: string; + organization: string; +} + +type Workspaces = WorkSpace[]; From 4a105a72e96f583bdfa3c87b8879f357ac71c9e8 Mon Sep 17 00:00:00 2001 From: seunghyunOh Date: Tue, 6 Dec 2022 05:55:07 +0900 Subject: [PATCH 21/24] Update comment for new util --- frontend/components/utilities/checks/tempLocalStorage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/components/utilities/checks/tempLocalStorage.ts b/frontend/components/utilities/checks/tempLocalStorage.ts index 85623a30a5..f24d53aeb3 100644 --- a/frontend/components/utilities/checks/tempLocalStorage.ts +++ b/frontend/components/utilities/checks/tempLocalStorage.ts @@ -1,4 +1,4 @@ -// this function is temporary until. have to create error handling logic for localStorage and delete this. +// this is temporary util function. create error handling logic for localStorage and delete this. export const tempLocalStorage = (key: string) => { const value = localStorage.getItem(key); From 9e73b3431ee3bf3883cf7b39c81ccbf2460cfac9 Mon Sep 17 00:00:00 2001 From: seunghyunOh Date: Tue, 6 Dec 2022 06:15:58 +0900 Subject: [PATCH 22/24] Delete workspace type file --- frontend/pages/api/workspace/getWorkspaces.ts | 10 ++++++++-- frontend/types/workspaces.d.ts | 8 -------- 2 files changed, 8 insertions(+), 10 deletions(-) delete mode 100644 frontend/types/workspaces.d.ts diff --git a/frontend/pages/api/workspace/getWorkspaces.ts b/frontend/pages/api/workspace/getWorkspaces.ts index 619041fdeb..33292b6eec 100644 --- a/frontend/pages/api/workspace/getWorkspaces.ts +++ b/frontend/pages/api/workspace/getWorkspaces.ts @@ -1,7 +1,13 @@ -import { Workspaces } from "types/workspaces"; - import SecurityClient from "~/utilities/SecurityClient"; +interface Workspaces { + __v: number; + _id: string; + name: string; + organization: string; +} +[]; + /** * This route lets us get the workspaces of a certain user * @returns diff --git a/frontend/types/workspaces.d.ts b/frontend/types/workspaces.d.ts deleted file mode 100644 index 7b6fab001c..0000000000 --- a/frontend/types/workspaces.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -export interface WorkSpace { - __v: number; - _id: string; - name: string; - organization: string; -} - -type Workspaces = WorkSpace[]; From 944cc5b32c0a4fef1448da41e2989e0f8e59069d Mon Sep 17 00:00:00 2001 From: Vladyslav Matsiiako Date: Tue, 6 Dec 2022 02:27:28 -0500 Subject: [PATCH 23/24] Fixed the bug with start keys --- frontend/components/utilities/attemptLogin.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/components/utilities/attemptLogin.js b/frontend/components/utilities/attemptLogin.js index 767fcb400d..4c6852625c 100644 --- a/frontend/components/utilities/attemptLogin.js +++ b/frontend/components/utilities/attemptLogin.js @@ -134,8 +134,8 @@ const attemptLogin = async ( // If user is logging in for the first time, add the example keys if (isSignUp) { - await pushKeys( - { + await pushKeys({ + obj: { DATABASE_URL: [ "mongodb+srv://${DB_USERNAME}:${DB_PASSWORD}@mongodb.net", "personal", @@ -155,9 +155,9 @@ const attemptLogin = async ( WEBSITE_URL: ["http://localhost:3000", "shared"], STRIPE_SECRET_KEY: ["sk_test_7348oyho4hfq398HIUOH78", "shared"], }, - projectToLogin, - "Development" - ); + workspaceId: projectToLogin, + env: "Development" + }); } try { if (email) { From df1ade4f5fefb25709b620fc657dd11873a1922f Mon Sep 17 00:00:00 2001 From: Vladyslav Matsiiako Date: Tue, 6 Dec 2022 02:28:34 -0500 Subject: [PATCH 24/24] Changed [NAME]'s project to Example Project --- backend/src/helpers/signup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/helpers/signup.ts b/backend/src/helpers/signup.ts index 410c442b35..e26b9b3606 100644 --- a/backend/src/helpers/signup.ts +++ b/backend/src/helpers/signup.ts @@ -106,7 +106,7 @@ const initializeDefaultOrg = async ({ // initialize a default workspace inside the new organization const workspace = await createWorkspace({ - name: `${user.firstName}'s Project`, + name: `Example Project`, organizationId: organization._id.toString() });