This commit is contained in:
Maidul Islam
2022-12-04 22:37:59 -05:00
16 changed files with 95 additions and 85 deletions

View File

@@ -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",

View File

@@ -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"
);

View File

@@ -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]

View File

@@ -47,27 +47,44 @@ const supportOptions = [
],
];
export default function Navbar({ onButtonPressed }) {
const router = useRouter();
const [user, setUser] = useState({});
const [orgs, setOrgs] = useState([]);
const [currentOrg, setCurrentOrg] = useState([]);
export interface ICurrentOrg {
name: string;
}
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);
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<IUser | undefined>();
const [orgs, setOrgs] = useState([]);
const [currentOrg, setCurrentOrg] = useState<ICurrentOrg | undefined>();
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"
>
<div className="relative flex justify-start items-center cursor-pointer select-none py-2 px-2 rounded-md text-gray-400 hover:bg-white/10 duration-200 hover:text-gray-200 w-full">
@@ -238,9 +255,9 @@ export default function Navbar({ onButtonPressed }) {
<div className="flex flex-col items-start px-1 mt-3 mb-2">
{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; }) => (
<div
key={guidGenerator()}
onClick={() => {

View File

@@ -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);
})();

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -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;
}
});
};

View File

@@ -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", "");

View File

@@ -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");

View File

@@ -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");

View File

@@ -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");

View File

@@ -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;

View File

@@ -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 (
<div className="mx-6 lg:mx-0 w-full overflow-y-scroll pt-28 h-screen">
<div className="flex flex-col items-center text-gray-300 text-lg mx-auto max-w-2xl lg:max-w-3xl xl:max-w-4xl">
<div className="text-3xl font-bold text-left w-full pt-6">Your quick start guide</div>
<div className="mx-6 lg:mx-0 w-full overflow-y-scroll pt-20 h-screen">
<div className="flex flex-col items-center text-gray-300 text-lg mx-auto max-w-2xl lg:max-w-3xl xl:max-w-4xl py-6">
<div className="text-3xl font-bold text-left w-full">Your quick start guide</div>
<div className="text-md text-left w-full pt-2 pb-4 text-bunker-300">Click on the items below and follow the instructions.</div>
{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 })}

View File

@@ -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,

View File

@@ -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() {
<div className="py-2"></div>
)}
</div>
<div className="flex flex-col items-center justify-center w-full md:px-4 md:py-5 mt-2 px-2 py-3 max-h-24 max-w-md mx-auto text-lg">
<div className="flex flex-col items-center justify-center md:px-4 md:py-5 mt-2 px-2 py-3 max-h-24 max-w-max mx-auto text-lg">
<Button
text="Sign Up"
onButtonPressed={() => {