lint(frontend): apply two space instead of tab

This commit is contained in:
이강준
2022-11-27 16:17:21 +09:00
parent 66d2a2724e
commit ef234a270f
104 changed files with 7883 additions and 8426 deletions
+1 -2
View File
@@ -2,9 +2,8 @@ import { useEffect, useState } from "react";
import Image from "next/image"; import Image from "next/image";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import checkAuth from "~/pages/api/auth/CheckAuth";
import { publicPaths } from "~/const"; import { publicPaths } from "~/const";
import checkAuth from "~/pages/api/auth/CheckAuth";
// #TODO: finish spinner only when the data loads fully // #TODO: finish spinner only when the data loads fully
// #TODO: Redirect somewhere if the page does not exist // #TODO: Redirect somewhere if the page does not exist
+6 -1
View File
@@ -1,6 +1,11 @@
import posthog from "posthog-js"; import posthog from "posthog-js";
import { ENV, POSTHOG_API_KEY, POSTHOG_HOST, TELEMETRY_ENABLED } from "../utilities/config"; import {
ENV,
POSTHOG_API_KEY,
POSTHOG_HOST,
TELEMETRY_ENABLED,
} from "../utilities/config";
export const initPostHog = () => { export const initPostHog = () => {
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
+1 -3
View File
@@ -10,9 +10,7 @@ export default function Error({ text }) {
className="text-white mt-1.5 mb-2 mx-2" className="text-white mt-1.5 mb-2 mx-2"
/> />
{text && ( {text && (
<p className="relative top-0 text-white mr-2 text-sm py-1"> <p className="relative top-0 text-white mr-2 text-sm py-1">{text}</p>
{text}
</p>
)} )}
</div> </div>
); );
+1 -3
View File
@@ -76,9 +76,7 @@ const InputField = (props) => {
? "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 props.error ? "focus:ring-red/50" : "focus:ring-primary/50"
? "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`} } 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} name={props.name}
spellCheck="false" spellCheck="false"
+13 -10
View File
@@ -1,7 +1,11 @@
import React from "react"; import React from "react";
import { Fragment } from "react"; import { Fragment } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { faAngleDown,faCheck, faPlus } from "@fortawesome/free-solid-svg-icons"; import {
faAngleDown,
faCheck,
faPlus,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Listbox, Transition } from "@headlessui/react"; import { Listbox, Transition } from "@headlessui/react";
@@ -38,7 +42,7 @@ export default function ListBox({
</div> </div>
{data && ( {data && (
<div className="cursor-pointer pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"> <div className="cursor-pointer pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
<FontAwesomeIcon icon={faAngleDown} className="text-md mr-1.5"/> <FontAwesomeIcon icon={faAngleDown} className="text-md mr-1.5" />
</div> </div>
)} )}
</Listbox.Button> </Listbox.Button>
@@ -55,9 +59,7 @@ export default function ListBox({
key={personIdx} key={personIdx}
className={({ active, selected }) => className={({ active, selected }) =>
`my-0.5 relative cursor-default select-none py-2 pl-10 pr-4 rounded-md ${ `my-0.5 relative cursor-default select-none py-2 pl-10 pr-4 rounded-md ${
selected selected ? "bg-white/10 text-gray-400 font-bold" : ""
? "bg-white/10 text-gray-400 font-bold"
: ""
} ${ } ${
active & !selected active & !selected
? "bg-white/5 text-mineshaft-200 cursor-pointer" ? "bg-white/5 text-mineshaft-200 cursor-pointer"
@@ -70,16 +72,17 @@ export default function ListBox({
<> <>
<span <span
className={`block truncate text-primary${ className={`block truncate text-primary${
selected selected ? "font-medium" : "font-normal"
? "font-medium"
: "font-normal"
}`} }`}
> >
{person} {person}
</span> </span>
{selected ? ( {selected ? (
<span className="text-primary rounded-lg absolute inset-y-0 left-0 flex items-center pl-3"> <span className="text-primary rounded-lg absolute inset-y-0 left-0 flex items-center pl-3">
<FontAwesomeIcon icon={faCheck} className="text-md ml-1"/> <FontAwesomeIcon
icon={faCheck}
className="text-md ml-1"
/>
</span> </span>
) : null} ) : null}
</> </>
@@ -93,7 +96,7 @@ export default function ListBox({
> >
<div className="my-0.5 relative flex justify-start cursor-pointer select-none py-2 pl-10 pr-4 rounded-md text-gray-400 hover:bg-lime-300 duration-200 hover:text-black hover:font-semibold mt-2"> <div className="my-0.5 relative flex justify-start cursor-pointer select-none py-2 pl-10 pr-4 rounded-md text-gray-400 hover:bg-lime-300 duration-200 hover:text-black hover:font-semibold mt-2">
<span className="rounded-lg absolute inset-y-0 left-0 flex items-center pl-3 pr-4"> <span className="rounded-lg absolute inset-y-0 left-0 flex items-center pl-3 pr-4">
<FontAwesomeIcon icon={faPlus} className="text-lg"/> <FontAwesomeIcon icon={faPlus} className="text-lg" />
</span> </span>
Add Project Add Project
</div> </div>
+16 -16
View File
@@ -16,7 +16,7 @@ export default function Button({
icon, icon,
active = true, active = true,
iconDisabled, iconDisabled,
textDisabled textDisabled,
}) { }) {
let styleButton = classNames( let styleButton = classNames(
"group m-auto md:m-0 inline-block rounded-md duration-200", "group m-auto md:m-0 inline-block rounded-md duration-200",
@@ -36,7 +36,7 @@ export default function Button({
size == "lg" && "h-12 w-full px-2 md:px-8", size == "lg" && "h-12 w-full px-2 md:px-8",
!size && "md:py-1 px-3 md:px-8", !size && "md:py-1 px-3 md:px-8",
size == "icon-md" && "h-10 w-10 flex items-center justify-center", size == "icon-md" && "h-10 w-10 flex items-center justify-center",
size == "icon-sm" && "h-9 w-9 flex items-center justify-center", size == "icon-sm" && "h-9 w-9 flex items-center justify-center"
); );
let styleMainDiv = classNames( let styleMainDiv = classNames(
@@ -48,7 +48,7 @@ export default function Button({
color == "red" && "text-gray-200", color == "red" && "text-gray-200",
active && color != "red" ? "group-hover:text-black" : "", active && color != "red" ? "group-hover:text-black" : "",
size == "icon" && "flex items-center justify-center", size == "icon" && "flex items-center justify-center"
); );
let textStyle = classNames( let textStyle = classNames(
@@ -80,25 +80,25 @@ export default function Button({
className={`rounded-xl`} className={`rounded-xl`}
></Image> ></Image>
</div> </div>
{icon && {icon && (
<FontAwesomeIcon <FontAwesomeIcon
icon={icon} icon={icon}
className={`flex my-auto font-extrabold ${size == "icon-sm" ? "text-sm" : "text-md"} ${(text || textDisabled) && "mr-2"}`} className={`flex my-auto font-extrabold ${
size == "icon-sm" ? "text-sm" : "text-md"
} ${(text || textDisabled) && "mr-2"}`}
/> />
} )}
{iconDisabled && {iconDisabled && (
<FontAwesomeIcon <FontAwesomeIcon
icon={iconDisabled} icon={iconDisabled}
className={`flex my-auto font-extrabold ${size == "icon-sm" ? "text-sm" : "text-md"} ${(text || textDisabled) && "mr-2"}`} className={`flex my-auto font-extrabold ${
size == "icon-sm" ? "text-sm" : "text-md"
} ${(text || textDisabled) && "mr-2"}`}
/> />
} )}
{(text || textDisabled) && {(text || textDisabled) && (
<p <p className={textStyle}>{active ? text : textDisabled}</p>
className={textStyle} )}
>
{active ? text : textDisabled}
</p>
}
</div> </div>
</button> </button>
); );
@@ -21,7 +21,10 @@ const AddIncidentContactDialog = ({
? incidentContacts.concat([incidentContactEmail]) ? incidentContacts.concat([incidentContactEmail])
: [incidentContactEmail] : [incidentContactEmail]
); );
addIncidentContact(localStorage.getItem("orgData.id"), incidentContactEmail); addIncidentContact(
localStorage.getItem("orgData.id"),
incidentContactEmail
);
closeModal(); closeModal();
}; };
return ( return (
@@ -60,16 +63,14 @@ const AddIncidentContactDialog = ({
</Dialog.Title> </Dialog.Title>
<div className="mt-2 mb-2"> <div className="mt-2 mb-2">
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
This contact will be notified in the This contact will be notified in the unlikely event of a
unlikely event of a severe incident. severe incident.
</p> </p>
</div> </div>
<div className="max-h-28"> <div className="max-h-28">
<InputField <InputField
label="Email" label="Email"
onChangeHandler={ onChangeHandler={setIncidentContactEmail}
setIncidentContactEmail
}
type="varName" type="varName"
value={incidentContactEmail} value={incidentContactEmail}
placeholder="" placeholder=""
@@ -56,26 +56,21 @@ const AddProjectMemberDialog = ({
as="h3" as="h3"
className="text-lg font-medium leading-6 text-gray-400 z-50" className="text-lg font-medium leading-6 text-gray-400 z-50"
> >
All the users in your organization All the users in your organization are already invited.
are already invited.
</Dialog.Title> </Dialog.Title>
)} )}
<div className="mt-2 mb-4"> <div className="mt-2 mb-4">
{data?.length > 0 ? ( {data?.length > 0 ? (
<div className="flex flex-col"> <div className="flex flex-col">
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
The user will receive an email The user will receive an email with the instructions.
with the instructions.
</p> </p>
<div className=""> <div className="">
<button <button
type="button" type="button"
className="inline-flex justify-center rounded-md py-1 text-sm text-gray-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2" className="inline-flex justify-center rounded-md py-1 text-sm text-gray-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
onClick={() => onClick={() =>
router.push( router.push("/settings/org/" + router.query.id)
"/settings/org/" +
router.query.id
)
} }
> >
If you are looking to add users to your org, If you are looking to add users to your org,
@@ -85,9 +80,7 @@ const AddProjectMemberDialog = ({
className="ml-1 inline-flex justify-center rounded-md py-1 text-sm text-gray-500 hover:text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2" className="ml-1 inline-flex justify-center rounded-md py-1 text-sm text-gray-500 hover:text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
onClick={() => onClick={() =>
router.push( router.push(
"/settings/org/" + "/settings/org/" + router.query.id + "?invite"
router.query.id +
"?invite"
) )
} }
> >
@@ -97,17 +90,14 @@ const AddProjectMemberDialog = ({
</div> </div>
) : ( ) : (
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
Add more users to the Add more users to the organization first.
organization first.
</p> </p>
)} )}
</div> </div>
<div className="max-h-28"> <div className="max-h-28">
{data?.length > 0 && ( {data?.length > 0 && (
<ListBox <ListBox
selected={ selected={email ? email : data[0]}
email ? email : data[0]
}
onChange={setEmail} onChange={setEmail}
data={data} data={data}
width="full" width="full"
@@ -127,10 +117,7 @@ const AddProjectMemberDialog = ({
) : ( ) : (
<Button <Button
onButtonPressed={() => onButtonPressed={() =>
router.push( router.push("/settings/org/" + router.query.id)
"/settings/org/" +
router.query.id
)
} }
color="mineshaft" color="mineshaft"
text="Add Users to Organization" text="Add Users to Organization"
@@ -8,7 +8,10 @@ import nacl from "tweetnacl";
import addServiceToken from "~/pages/api/serviceToken/addServiceToken"; import addServiceToken from "~/pages/api/serviceToken/addServiceToken";
import getLatestFileKey from "~/pages/api/workspace/getLatestFileKey"; import getLatestFileKey from "~/pages/api/workspace/getLatestFileKey";
import { decryptAssymmetric, encryptAssymmetric } from "../../utilities/cryptography/crypto"; import {
decryptAssymmetric,
encryptAssymmetric,
} from "../../utilities/cryptography/crypto";
import Button from "../buttons/Button"; import Button from "../buttons/Button";
import InputField from "../InputField"; import InputField from "../InputField";
import ListBox from "../Listbox"; import ListBox from "../Listbox";
@@ -131,28 +134,22 @@ const AddServiceTokenDialog = ({
as="h3" as="h3"
className="text-lg font-medium leading-6 text-gray-400 z-50" className="text-lg font-medium leading-6 text-gray-400 z-50"
> >
Add a service token for{" "} Add a service token for {workspaceName}
{workspaceName}
</Dialog.Title> </Dialog.Title>
<div className="mt-2 mb-4"> <div className="mt-2 mb-4">
<div className="flex flex-col"> <div className="flex flex-col">
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
Specify the name, Specify the name, environment, and expiry period. When
environment, and expiry a token is generated, you will only be able to see it
period. When a token is once before it disappears. Make sure to save it
generated, you will only be somewhere.
able to see it once before
it disappears. Make sure to
save it somewhere.
</p> </p>
</div> </div>
</div> </div>
<div className="max-h-28 mb-2"> <div className="max-h-28 mb-2">
<InputField <InputField
label="Service Token Name" label="Service Token Name"
onChangeHandler={ onChangeHandler={setServiceTokenName}
setServiceTokenName
}
type="varName" type="varName"
value={serviceTokenName} value={serviceTokenName}
placeholder="" placeholder=""
@@ -176,14 +173,8 @@ const AddServiceTokenDialog = ({
<div className="max-h-28"> <div className="max-h-28">
<ListBox <ListBox
selected={serviceTokenExpiresIn} selected={serviceTokenExpiresIn}
onChange={ onChange={setServiceTokenExpiresIn}
setServiceTokenExpiresIn data={["1 day", "7 days", "1 month"]}
}
data={[
"1 day",
"7 days",
"1 month",
]}
width="full" width="full"
text="Expires in: " text="Expires in: "
/> />
@@ -191,18 +182,12 @@ const AddServiceTokenDialog = ({
<div className="max-w-max"> <div className="max-w-max">
<div className="mt-6 flex flex-col justify-start w-max"> <div className="mt-6 flex flex-col justify-start w-max">
<Button <Button
onButtonPressed={() => onButtonPressed={() => generateServiceToken()}
generateServiceToken()
}
color="mineshaft" color="mineshaft"
text="Add Service Token" text="Add Service Token"
textDisabled="Add Service Token" textDisabled="Add Service Token"
size="md" size="md"
active={ active={serviceTokenName == "" ? false : true}
serviceTokenName == ""
? false
: true
}
/> />
</div> </div>
</div> </div>
@@ -218,8 +203,7 @@ const AddServiceTokenDialog = ({
<div className="mt-2 mb-4"> <div className="mt-2 mb-4">
<div className="flex flex-col"> <div className="flex flex-col">
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
Once you close this popup, Once you close this popup, you will never see your
you will never see your
service token again service token again
</p> </p>
</div> </div>
@@ -237,9 +221,7 @@ const AddServiceTokenDialog = ({
</div> </div>
<div className="group font-normal h-full relative inline-block text-gray-400 underline hover:text-primary duration-200"> <div className="group font-normal h-full relative inline-block text-gray-400 underline hover:text-primary duration-200">
<button <button
onClick={ onClick={copyToClipboard}
copyToClipboard
}
className="h-full pl-3.5 pr-4 border-l border-white/20 py-2 hover:bg-white/[0.12] duration-200" className="h-full pl-3.5 pr-4 border-l border-white/20 py-2 hover:bg-white/[0.12] duration-200"
> >
{serviceTokenCopied ? ( {serviceTokenCopied ? (
@@ -248,9 +230,7 @@ const AddServiceTokenDialog = ({
className="pr-0.5" className="pr-0.5"
/> />
) : ( ) : (
<FontAwesomeIcon <FontAwesomeIcon icon={faCopy} />
icon={faCopy}
/>
)} )}
</button> </button>
<span className="absolute hidden group-hover:flex group-hover:animate-popup duration-300 w-28 -left-8 -top-20 translate-y-full px-3 py-2 bg-chicago-900 rounded-md text-center text-gray-400 text-sm"> <span className="absolute hidden group-hover:flex group-hover:animate-popup duration-300 w-28 -left-8 -top-20 translate-y-full px-3 py-2 bg-chicago-900 rounded-md text-center text-gray-400 text-sm">
@@ -261,9 +241,7 @@ const AddServiceTokenDialog = ({
</div> </div>
<div className="mt-6 flex flex-col justify-start w-max"> <div className="mt-6 flex flex-col justify-start w-max">
<Button <Button
onButtonPressed={() => onButtonPressed={() => closeAddServiceTokenModal()}
closeAddServiceTokenModal()
}
color="mineshaft" color="mineshaft"
text="Close" text="Close"
size="md" size="md"
@@ -14,7 +14,7 @@ const AddUserDialog = ({
workspaceId, workspaceId,
setEmail, setEmail,
currentPlan, currentPlan,
orgName orgName,
}) => { }) => {
const submit = () => { const submit = () => {
submitModal(email); submitModal(email);
@@ -57,9 +57,9 @@ const AddUserDialog = ({
</Dialog.Title> </Dialog.Title>
<div className="mt-2 mb-4"> <div className="mt-2 mb-4">
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
An invite is specific to an email address An invite is specific to an email address and expires
and expires after 1 day. For security reasons, after 1 day. For security reasons, you will need to
you will need to separately add members to projects. separately add members to projects.
</p> </p>
</div> </div>
<div className="max-h-28"> <div className="max-h-28">
@@ -72,15 +72,13 @@ const AddUserDialog = ({
isRequired isRequired
/> />
</div> </div>
{currentPlan == STRIPE_PRODUCT_STARTER && <div className="flex flex-row"> {currentPlan == STRIPE_PRODUCT_STARTER && (
<div className="flex flex-row">
<button <button
type="button" type="button"
className="inline-flex justify-center rounded-md py-1 text-sm text-gray-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2" className="inline-flex justify-center rounded-md py-1 text-sm text-gray-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
onClick={() => onClick={() =>
router.push( router.push("/settings/billing/" + router.query.id)
"/settings/billing/" +
router.query.id
)
} }
> >
You can add up to 5 members on a Free tier. You can add up to 5 members on a Free tier.
@@ -89,15 +87,13 @@ const AddUserDialog = ({
type="button" type="button"
className="ml-1 inline-flex justify-center rounded-md py-1 text-sm text-gray-500 hover:text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2" className="ml-1 inline-flex justify-center rounded-md py-1 text-sm text-gray-500 hover:text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
onClick={() => onClick={() =>
router.push( router.push("/settings/billing/" + router.query.id)
"/settings/billing/" +
router.query.id
)
} }
> >
Upgrade now. Upgrade now.
</button> </button>
</div>} </div>
)}
<div className="mt-4 max-w-max"> <div className="mt-4 max-w-max">
<Button <Button
onButtonPressed={submit} onButtonPressed={submit}
@@ -61,8 +61,7 @@ const AddWorkspaceDialog = ({
</Dialog.Title> </Dialog.Title>
<div className="mt-2"> <div className="mt-2">
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
This project will contain your This project will contain your environmental variables.
environmental variables.
</p> </p>
</div> </div>
<div className="max-h-28 mt-4"> <div className="max-h-28 mt-4">
@@ -1,15 +1,19 @@
import { Fragment, useState } from 'react' import { Fragment, useState } from "react";
import { Dialog, Transition } from '@headlessui/react' import { Dialog, Transition } from "@headlessui/react";
import InputField from '../InputField'; import InputField from "../InputField";
// #TODO: USE THIS. Currently it's not. Kinda complicated to set up because of state. // #TODO: USE THIS. Currently it's not. Kinda complicated to set up because of state.
const DeleteUserDialog = ({
const DeleteUserDialog = ({isOpen, closeModal, submitModal, userIdToBeDeleted}) => { isOpen,
closeModal,
submitModal,
userIdToBeDeleted,
}) => {
const submit = () => { const submit = () => {
submitModal(userIdToBeDeleted); submitModal(userIdToBeDeleted);
} };
return ( return (
<div> <div>
<Transition appear show={isOpen} as={Fragment}> <Transition appear show={isOpen} as={Fragment}>
@@ -42,7 +46,8 @@ const DeleteUserDialog = ({isOpen, closeModal, submitModal, userIdToBeDeleted})
as="h3" as="h3"
className="text-lg font-medium leading-6 text-gray-400" className="text-lg font-medium leading-6 text-gray-400"
> >
Are you sure you want to remove this user from the workspace? Are you sure you want to remove this user from the
workspace?
</Dialog.Title> </Dialog.Title>
<div className="mt-2"> <div className="mt-2">
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
+20 -54
View File
@@ -20,7 +20,10 @@ import createWorkspace from "~/pages/api/workspace/createWorkspace";
import getWorkspaces from "~/pages/api/workspace/getWorkspaces"; import getWorkspaces from "~/pages/api/workspace/getWorkspaces";
import NavBarDashboard from "../navigation/NavBarDashboard"; import NavBarDashboard from "../navigation/NavBarDashboard";
import { decryptAssymmetric, encryptAssymmetric } from "../utilities/cryptography/crypto"; import {
decryptAssymmetric,
encryptAssymmetric,
} from "../utilities/cryptography/crypto";
import Button from "./buttons/Button"; import Button from "./buttons/Button";
import AddWorkspaceDialog from "./dialog/AddWorkspaceDialog"; import AddWorkspaceDialog from "./dialog/AddWorkspaceDialog";
import Listbox from "./Listbox"; import Listbox from "./Listbox";
@@ -72,8 +75,7 @@ export default function Layout({ children }) {
newWorkspaceId newWorkspaceId
); );
if (result?.invitee && result?.latestKey) { if (result?.invitee && result?.latestKey) {
const PRIVATE_KEY = const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY");
localStorage.getItem("PRIVATE_KEY");
// assymmetrically decrypt symmetric key with local private key // assymmetrically decrypt symmetric key with local private key
const key = decryptAssymmetric({ const key = decryptAssymmetric({
@@ -89,12 +91,7 @@ export default function Layout({ children }) {
privateKey: PRIVATE_KEY, privateKey: PRIVATE_KEY,
}); });
uploadKeys( uploadKeys(newWorkspaceId, result.invitee._id, ciphertext, nonce);
newWorkspaceId,
result.invitee._id,
ciphertext,
nonce
);
} }
} }
}); });
@@ -115,9 +112,7 @@ export default function Layout({ children }) {
const menuItems = [ const menuItems = [
{ {
href: href:
"/dashboard/" + "/dashboard/" + workspaceMapping[workspaceSelected] + "?Development",
workspaceMapping[workspaceSelected] +
"?Development",
title: "Secrets", title: "Secrets",
emoji: <FontAwesomeIcon icon={faHouse} />, emoji: <FontAwesomeIcon icon={faHouse} />,
}, },
@@ -170,27 +165,17 @@ export default function Layout({ children }) {
.map((workspace) => workspace._id) .map((workspace) => workspace._id)
.includes(intendedWorkspaceId) .includes(intendedWorkspaceId)
) { ) {
router.push( router.push("/dashboard/" + userWorkspaces[0]._id + "?Development");
"/dashboard/" + userWorkspaces[0]._id + "?Development"
);
} else { } else {
setWorkspaceList( setWorkspaceList(userWorkspaces.map((workspace) => workspace.name));
userWorkspaces.map((workspace) => workspace.name)
);
setWorkspaceMapping( setWorkspaceMapping(
Object.fromEntries( Object.fromEntries(
userWorkspaces.map((workspace) => [ userWorkspaces.map((workspace) => [workspace.name, workspace._id])
workspace.name,
workspace._id,
])
) )
); );
setWorkspaceSelected( setWorkspaceSelected(
Object.fromEntries( Object.fromEntries(
userWorkspaces.map((workspace) => [ userWorkspaces.map((workspace) => [workspace._id, workspace.name])
workspace._id,
workspace.name,
])
)[ )[
router.asPath router.asPath
.split("/") .split("/")
@@ -211,9 +196,7 @@ export default function Layout({ children }) {
[router.asPath.split("/").length - 1].split("?")[0] [router.asPath.split("/").length - 1].split("?")[0]
) { ) {
router.push( router.push(
"/dashboard/" + "/dashboard/" + workspaceMapping[workspaceSelected] + "?Development"
workspaceMapping[workspaceSelected] +
"?Development"
); );
localStorage.setItem( localStorage.setItem(
"projectData.id", "projectData.id",
@@ -260,37 +243,22 @@ export default function Layout({ children }) {
{workspaceList.length > 0 && {workspaceList.length > 0 &&
menuItems.map(({ href, title, emoji }) => ( menuItems.map(({ href, title, emoji }) => (
<li className="mt-1.5 mx-2" key={title}> <li className="mt-1.5 mx-2" key={title}>
{router.asPath.split("/")[1] === {router.asPath.split("/")[1] === href.split("/")[1] &&
href.split("/")[1] && (["project", "billing", "org", "personal"].includes(
([
"project",
"billing",
"org",
"personal",
].includes(
router.asPath.split("/")[2] router.asPath.split("/")[2]
) )
? router.asPath.split( ? router.asPath.split("/")[2] === href.split("/")[2]
"/"
)[2] === href.split("/")[2]
: true) ? ( : true) ? (
<div <div
className={`flex p-2 text-white text-sm rounded cursor-pointer bg-mineshaft-50/10`} className={`flex p-2 text-white text-sm rounded cursor-pointer bg-mineshaft-50/10`}
> >
<div className="bg-primary w-1 rounded-xl mr-1"></div> <div className="bg-primary w-1 rounded-xl mr-1"></div>
<p className="ml-2 mr-4"> <p className="ml-2 mr-4">{emoji}</p>
{emoji}
</p>
{title} {title}
</div> </div>
) : router.asPath == ) : router.asPath == "/noprojects" ? (
"/noprojects" ? ( <div className={`flex p-2 text-white text-sm rounded`}>
<div <p className="ml-2 mr-4">{emoji}</p>
className={`flex p-2 text-white text-sm rounded`}
>
<p className="ml-2 mr-4">
{emoji}
</p>
{title} {title}
</div> </div>
) : ( ) : (
@@ -298,9 +266,7 @@ export default function Layout({ children }) {
<div <div
className={`flex p-2 text-white text-sm rounded cursor-pointer hover:bg-mineshaft-50/5`} className={`flex p-2 text-white text-sm rounded cursor-pointer hover:bg-mineshaft-50/5`}
> >
<p className="ml-2 mr-4"> <p className="ml-2 mr-4">{emoji}</p>
{emoji}
</p>
{title} {title}
</div> </div>
</Link> </Link>
@@ -8,11 +8,11 @@ import Button from "../buttons/Button";
const roles = ["admin", "user"]; const roles = ["admin", "user"];
const reverseEnvMapping = { const reverseEnvMapping = {
"dev": "Development", dev: "Development",
"staging": "Staging", staging: "Staging",
"prod": "Production", prod: "Production",
"test": "Testing" test: "Testing",
} };
/** /**
* This is the component that we utilize for the user table - in future, can reuse it for some other purposes too. * This is the component that we utilize for the user table - in future, can reuse it for some other purposes too.
@@ -20,10 +20,7 @@ const reverseEnvMapping = {
* @param {*} props * @param {*} props
* @returns * @returns
*/ */
const ServiceTokenTable = ({ const ServiceTokenTable = ({ data, workspaceName }) => {
data,
workspaceName
}) => {
const router = useRouter(); const router = useRouter();
return ( return (
@@ -40,11 +37,13 @@ const ServiceTokenTable = ({
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{data?.length > 0 {data?.length > 0 ? (
? data data.map((row, index) => {
.map((row, index) => {
return ( return (
<tr key={guidGenerator()} className="bg-bunker-800 hover:bg-bunker-800/5 duration-100"> <tr
key={guidGenerator()}
className="bg-bunker-800 hover:bg-bunker-800/5 duration-100"
>
<td className="pl-6 py-2 border-mineshaft-700 border-t text-gray-300"> <td className="pl-6 py-2 border-mineshaft-700 border-t text-gray-300">
{row.name} {row.name}
</td> </td>
@@ -70,9 +69,13 @@ const ServiceTokenTable = ({
</tr> </tr>
); );
}) })
: <tr> ) : (
<td colSpan="4" className="text-center pt-7 pb-4 text-bunker-400">No service tokens yet</td> <tr>
</tr>} <td colSpan="4" className="text-center pt-7 pb-4 text-bunker-400">
No service tokens yet
</td>
</tr>
)}
</tbody> </tbody>
</table> </table>
</div> </div>
+13 -44
View File
@@ -137,12 +137,8 @@ const UserTable = ({
userData userData
?.filter( ?.filter(
(user) => (user) =>
user.firstName user.firstName?.toLowerCase().includes(filter) ||
?.toLowerCase() user.lastName?.toLowerCase().includes(filter) ||
.includes(filter) ||
user.lastName
?.toLowerCase()
.includes(filter) ||
user.email?.toLowerCase().includes(filter) user.email?.toLowerCase().includes(filter)
) )
.map((row, index) => { .map((row, index) => {
@@ -163,51 +159,32 @@ const UserTable = ({
<td className="flex flex-row justify-end pr-8 py-2 border-t border-0.5 border-mineshaft-700"> <td className="flex flex-row justify-end pr-8 py-2 border-t border-0.5 border-mineshaft-700">
<div className="flex justify-end mr-6 w-3/4 mx-2 w-full h-full flex flex-row items-center"> <div className="flex justify-end mr-6 w-3/4 mx-2 w-full h-full flex flex-row items-center">
{row.status == "granted" && {row.status == "granted" &&
((myRole == "admin" && ((myRole == "admin" && row.role != "owner") ||
row.role != "owner") ||
myRole == "owner") && myRole == "owner") &&
myUser !== row.email ? ( myUser !== row.email ? (
<Listbox <Listbox
selected={row.role} selected={row.role}
onChange={(e) => onChange={(e) => handleRoleUpdate(index, e)}
handleRoleUpdate(
index,
e
)
}
data={ data={
myRole == "owner" myRole == "owner"
? [ ? ["owner", "admin", "member"]
"owner", : ["admin", "member"]
"admin",
"member",
]
: [
"admin",
"member",
]
} }
text="Role: " text="Role: "
membershipId={ membershipId={row.membershipId}
row.membershipId
}
/> />
) : ( ) : (
row.status != "invited" && row.status != "invited" &&
row.status != row.status != "verified" && (
"verified" && (
<Listbox <Listbox
selected={row.role} selected={row.role}
text="Role: " text="Role: "
membershipId={ membershipId={row.membershipId}
row.membershipId
}
/> />
) )
)} )}
{(row.status == "invited" || {(row.status == "invited" ||
row.status == row.status == "verified") && (
"verified") && (
<div className="w-full pl-12"> <div className="w-full pl-12">
<Button <Button
onButtonPressed={() => onButtonPressed={() =>
@@ -222,15 +199,11 @@ const UserTable = ({
/> />
</div> </div>
)} )}
{row.status == "completed" && {row.status == "completed" && myUser !== row.email && (
myUser !== row.email && (
<div className="border border-mineshaft-700 rounded-md bg-white/5 hover:bg-primary text-white hover:text-black duration-200"> <div className="border border-mineshaft-700 rounded-md bg-white/5 hover:bg-primary text-white hover:text-black duration-200">
<Button <Button
onButtonPressed={() => onButtonPressed={() =>
grantAccess( grantAccess(row.userId, row.publicKey)
row.userId,
row.publicKey
)
} }
color="mineshaft" color="mineshaft"
text="Grant Access" text="Grant Access"
@@ -245,11 +218,7 @@ const UserTable = ({
<div className="opacity-50 hover:opacity-100 flex items-center"> <div className="opacity-50 hover:opacity-100 flex items-center">
<Button <Button
onButtonPressed={(e) => onButtonPressed={(e) =>
handleDelete( handleDelete(row.membershipId, index, e)
row.membershipId,
index,
e
)
} }
color="red" color="red"
size="icon-sm" size="icon-sm"
+4 -13
View File
@@ -14,9 +14,7 @@ export default function Plan({ plan }) {
> >
<div className="flex flex-col"> <div className="flex flex-col">
<div className="flex flex-row justify-between items-center relative z-10"> <div className="flex flex-row justify-between items-center relative z-10">
<p <p className={`px-6 py-4 text-3xl font-semibold text-gray-400`}>
className={`px-6 py-4 text-3xl font-semibold text-gray-400`}
>
{plan.name} {plan.name}
</p> </p>
</div> </div>
@@ -39,10 +37,7 @@ export default function Plan({ plan }) {
{plan.current == false ? ( {plan.current == false ? (
<> <>
{plan.buttonTextMain == "Schedule a Demo" ? ( {plan.buttonTextMain == "Schedule a Demo" ? (
<a <a href="/scheduledemo" target='_blank rel="noopener"'>
href="/scheduledemo"
target='_blank rel="noopener"'
>
<div className="relative z-10 mx-5 mt-3 mb-4 py-2 px-4 border border-1 border-gray-600 hover:text-black hover:border-primary text-gray-400 font-semibold hover:bg-primary bg-bunker duration-200 cursor-pointer rounded-md flex w-max"> <div className="relative z-10 mx-5 mt-3 mb-4 py-2 px-4 border border-1 border-gray-600 hover:text-black hover:border-primary text-gray-400 font-semibold hover:bg-primary bg-bunker duration-200 cursor-pointer rounded-md flex w-max">
{plan.buttonTextMain} {plan.buttonTextMain}
</div> </div>
@@ -58,9 +53,7 @@ export default function Plan({ plan }) {
<button <button
onClick={() => onClick={() =>
StripeRedirect({ StripeRedirect({
orgId: localStorage.getItem( orgId: localStorage.getItem("orgData.id"),
"orgData.id"
),
}) })
} }
> >
@@ -82,9 +75,7 @@ export default function Plan({ plan }) {
: "bg-chicago-700" : "bg-chicago-700"
}`} }`}
> >
<p className="text-xs text-black font-semibold"> <p className="text-xs text-black font-semibold">CURRENT PLAN</p>
CURRENT PLAN
</p>
</div> </div>
)} )}
</div> </div>
@@ -89,30 +89,18 @@ const DashboardInputField = ({
); );
} }
return ( return (
<span <span className="ph-no-capture text-yellow" key={id}>
className="ph-no-capture text-yellow"
key={id}
>
{texts.slice(0, 2)} {texts.slice(0, 2)}
<span className="ph-no-capture text-yellow-200/80"> <span className="ph-no-capture text-yellow-200/80">
{texts.slice(2, texts.length - 1)} {texts.slice(2, texts.length - 1)}
</span> </span>
{texts.slice( {texts.slice(texts.length - 1, texts.length) == "}" ? (
texts.length - 1,
texts.length
) == "}" ? (
<span className="ph-no-capture text-yellow"> <span className="ph-no-capture text-yellow">
{texts.slice( {texts.slice(texts.length - 1, texts.length)}{" "}
texts.length - 1,
texts.length
)}{" "}
</span> </span>
) : ( ) : (
<span className="ph-no-capture text-yellow-400"> <span className="ph-no-capture text-yellow-400">
{texts.slice( {texts.slice(texts.length - 1, texts.length)}{" "}
texts.length - 1,
texts.length
)}{" "}
</span> </span>
)} )}
</span> </span>
+3 -4
View File
@@ -16,7 +16,7 @@ const DropZone = ({
addPresetRow, addPresetRow,
setButtonReady, setButtonReady,
keysExist, keysExist,
numCurrentRows numCurrentRows,
}) => { }) => {
const handleDragEnter = (e) => { const handleDragEnter = (e) => {
e.preventDefault(); e.preventDefault();
@@ -49,9 +49,8 @@ const DropZone = ({
var file = e.dataTransfer.files[0], var file = e.dataTransfer.files[0],
reader = new FileReader(); reader = new FileReader();
reader.onload = function (event) { reader.onload = function (event) {
const keyPairs = parse(event.target.result) const keyPairs = parse(event.target.result);
const newData = Object.keys(keyPairs) const newData = Object.keys(keyPairs).map((key, index) => [
.map((key, index) => [
guidGenerator(), guidGenerator(),
numCurrentRows + index, numCurrentRows + index,
key, key,
@@ -1,9 +1,9 @@
/* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable react/jsx-key */ /* eslint-disable react/jsx-key */
import React, { Fragment, useEffect,useState } from "react"; import React, { Fragment, useEffect, useState } from "react";
import Image from "next/image"; import Image from "next/image";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { faGithub,faSlack } from "@fortawesome/free-brands-svg-icons"; import { faGithub, faSlack } from "@fortawesome/free-brands-svg-icons";
import { faCircleQuestion } from "@fortawesome/free-regular-svg-icons"; import { faCircleQuestion } from "@fortawesome/free-regular-svg-icons";
import { import {
faAngleDown, faAngleDown,
@@ -82,19 +82,14 @@ export default function Navbar({ onButtonPressed }) {
alt="logo" alt="logo"
/> />
</div> </div>
<a className="text-2xl text-white font-semibold mx-2"> <a className="text-2xl text-white font-semibold mx-2">Infisical</a>
Infisical
</a>
</div> </div>
</div> </div>
<div className="relative flex justify-start items-center mx-2 z-40"> <div className="relative flex justify-start items-center mx-2 z-40">
<Menu as="div" className="relative inline-block text-left"> <Menu as="div" className="relative inline-block text-left">
<div className="mr-4"> <div className="mr-4">
<Menu.Button className="inline-flex w-full justify-center rounded-md px-2 py-2 text-sm font-medium text-gray-200 rounded-md hover:bg-white/10 duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75"> <Menu.Button className="inline-flex w-full justify-center rounded-md px-2 py-2 text-sm font-medium text-gray-200 rounded-md hover:bg-white/10 duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75">
<FontAwesomeIcon <FontAwesomeIcon className="text-xl" icon={faCircleQuestion} />
className="text-xl"
icon={faCircleQuestion}
/>
</Menu.Button> </Menu.Button>
</div> </div>
<Transition <Transition
@@ -118,9 +113,7 @@ export default function Navbar({ onButtonPressed }) {
> >
<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"> <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">
{option[0]} {option[0]}
<div className="text-sm"> <div className="text-sm">{option[1]}</div>
{option[1]}
</div>
</div> </div>
</a> </a>
))} ))}
@@ -153,10 +146,7 @@ export default function Navbar({ onButtonPressed }) {
</div> </div>
<div <div
onClick={() => onClick={() =>
router.push( router.push("/settings/personal/" + router.query.id)
"/settings/personal/" +
router.query.id
)
} }
className="flex flex-row items-center px-1 mx-1 my-1 hover:bg-white/5 cursor-pointer rounded-md" className="flex flex-row items-center px-1 mx-1 my-1 hover:bg-white/5 cursor-pointer rounded-md"
> >
@@ -167,8 +157,7 @@ export default function Navbar({ onButtonPressed }) {
<div> <div>
<p className="text-gray-300 px-2 pt-1 text-sm"> <p className="text-gray-300 px-2 pt-1 text-sm">
{" "} {" "}
{user?.firstName}{" "} {user?.firstName} {user?.lastName}
{user?.lastName}
</p> </p>
<p className="text-gray-400 px-2 pb-1 text-xs"> <p className="text-gray-400 px-2 pb-1 text-xs">
{" "} {" "}
@@ -188,9 +177,7 @@ export default function Navbar({ onButtonPressed }) {
</div> </div>
<div <div
onClick={() => onClick={() =>
router.push( router.push("/settings/org/" + router.query.id)
"/settings/org/" + router.query.id
)
} }
className="flex flex-row items-center px-2 mt-2 py-1 hover:bg-white/5 cursor-pointer rounded-md" className="flex flex-row items-center px-2 mt-2 py-1 hover:bg-white/5 cursor-pointer rounded-md"
> >
@@ -213,10 +200,7 @@ export default function Navbar({ onButtonPressed }) {
> >
<div <div
onClick={() => onClick={() =>
router.push( router.push("/settings/billing/" + router.query.id)
"/settings/billing/" +
router.query.id
)
} }
className="mt-1 relative flex justify-start cursor-pointer select-none py-2 px-2 rounded-md text-gray-400 hover:bg-white/5 duration-200 hover:text-gray-200" className="mt-1 relative flex justify-start cursor-pointer select-none py-2 px-2 rounded-md text-gray-400 hover:bg-white/5 duration-200 hover:text-gray-200"
> >
@@ -224,9 +208,7 @@ export default function Navbar({ onButtonPressed }) {
className="text-lg pl-1.5 pr-3" className="text-lg pl-1.5 pr-3"
icon={faCoins} icon={faCoins}
/> />
<div className="text-sm"> <div className="text-sm">Usage & Billing</div>
Usage & Billing
</div>
</div> </div>
</button> </button>
<button <button
@@ -236,22 +218,15 @@ export default function Navbar({ onButtonPressed }) {
<div <div
onClick={() => onClick={() =>
router.push( router.push(
"/settings/org/" + "/settings/org/" + router.query.id + "?invite"
router.query.id +
"?invite"
) )
} }
className="relative flex justify-start cursor-pointer select-none py-2 pl-10 pr-4 rounded-md text-gray-400 hover:bg-primary/100 duration-200 hover:text-black hover:font-semibold mt-1" className="relative flex justify-start cursor-pointer select-none py-2 pl-10 pr-4 rounded-md text-gray-400 hover:bg-primary/100 duration-200 hover:text-black hover:font-semibold mt-1"
> >
<span className="rounded-lg absolute inset-y-0 left-0 flex items-center pl-3 pr-4"> <span className="rounded-lg absolute inset-y-0 left-0 flex items-center pl-3 pr-4">
<FontAwesomeIcon <FontAwesomeIcon icon={faPlus} className="ml-1" />
icon={faPlus}
className="ml-1"
/>
</span> </span>
<div className="text-sm ml-1"> <div className="text-sm ml-1">Invite Members</div>
Invite Members
</div>
</div> </div>
</button> </button>
</div> </div>
@@ -263,20 +238,13 @@ export default function Navbar({ onButtonPressed }) {
<div className="flex flex-col items-start px-1 mt-3 mb-2"> <div className="flex flex-col items-start px-1 mt-3 mb-2">
{orgs {orgs
.filter( .filter(
(org) => (org) => org._id != localStorage.getItem("orgData.id")
org._id !=
localStorage.getItem(
"orgData.id"
)
) )
.map((org) => ( .map((org) => (
<div <div
key={guidGenerator()} key={guidGenerator()}
onClick={() => { onClick={() => {
localStorage.setItem( localStorage.setItem("orgData.id", org._id);
"orgData.id",
org._id
);
router.reload(); router.reload();
}} }}
className="flex flex-row justify-start items-center hover:bg-white/5 w-full p-1.5 cursor-pointer rounded-md" className="flex flex-row justify-start items-center hover:bg-white/5 w-full p-1.5 cursor-pointer rounded-md"
@@ -1,6 +1,5 @@
import token from "~/pages/api/auth/Token";
import { PATH } from "~/const"; import { PATH } from "~/const";
import token from "~/pages/api/auth/Token";
export default class SecurityClient { export default class SecurityClient {
static authOrigins = [PATH]; static authOrigins = [PATH];
+12 -38
View File
@@ -5,8 +5,8 @@ import getOrganizations from "~/pages/api/organization/getOrgs";
import getOrganizationUserProjects from "~/pages/api/organization/GetOrgUserProjects"; import getOrganizationUserProjects from "~/pages/api/organization/GetOrgUserProjects";
import { initPostHog } from "../analytics/posthog"; import { initPostHog } from "../analytics/posthog";
import { ENV } from "./config";
import pushKeys from "./secrets/pushKeys"; import pushKeys from "./secrets/pushKeys";
import { ENV } from "./config";
import SecurityClient from "./SecurityClient"; import SecurityClient from "./SecurityClient";
const nacl = require("tweetnacl"); const nacl = require("tweetnacl");
@@ -69,8 +69,7 @@ const attemptLogin = async (
response = await response.json(); response = await response.json();
SecurityClient.setToken(response["token"]); SecurityClient.setToken(response["token"]);
const publicKey = response["publicKey"]; const publicKey = response["publicKey"];
const encryptedPrivateKey = const encryptedPrivateKey = response["encryptedPrivateKey"];
response["encryptedPrivateKey"];
const iv = response["iv"]; const iv = response["iv"];
const tag = response["tag"]; const tag = response["tag"];
@@ -82,26 +81,21 @@ const attemptLogin = async (
.slice(0, 32) .slice(0, 32)
.padStart( .padStart(
32 + 32 +
(password.slice(0, 32).length - (password.slice(0, 32).length - new Blob([password]).size),
new Blob([password]).size),
"0" "0"
) )
); );
try { try {
localStorage.setItem("publicKey", publicKey); localStorage.setItem("publicKey", publicKey);
localStorage.setItem( localStorage.setItem("encryptedPrivateKey", encryptedPrivateKey);
"encryptedPrivateKey",
encryptedPrivateKey
);
localStorage.setItem("iv", iv); localStorage.setItem("iv", iv);
localStorage.setItem("tag", tag); localStorage.setItem("tag", tag);
localStorage.setItem("PRIVATE_KEY", PRIVATE_KEY); localStorage.setItem("PRIVATE_KEY", PRIVATE_KEY);
} catch (err) { } catch (err) {
setErrorLogin(true); setErrorLogin(true);
console.error( console.error(
"Unable to send the tokens in local storage:" + "Unable to send the tokens in local storage:" + err.message
err.message
); );
} }
} else { } else {
@@ -112,11 +106,7 @@ const attemptLogin = async (
const userOrgsData = userOrgs.map((org) => org._id); const userOrgsData = userOrgs.map((org) => org._id);
let orgToLogin; let orgToLogin;
if ( if (userOrgsData.includes(localStorage.getItem("orgData.id"))) {
userOrgsData.includes(
localStorage.getItem("orgData.id")
)
) {
orgToLogin = localStorage.getItem("orgData.id"); orgToLogin = localStorage.getItem("orgData.id");
} else { } else {
orgToLogin = userOrgsData[0]; orgToLogin = userOrgsData[0];
@@ -127,28 +117,18 @@ const attemptLogin = async (
orgId: orgToLogin, orgId: orgToLogin,
}); });
orgUserProjects = orgUserProjects?.map( orgUserProjects = orgUserProjects?.map((project) => project._id);
(project) => project._id
);
let projectToLogin; let projectToLogin;
if ( if (
orgUserProjects.includes( orgUserProjects.includes(localStorage.getItem("projectData.id"))
localStorage.getItem("projectData.id")
)
) { ) {
projectToLogin = localStorage.getItem("projectData.id"); projectToLogin = localStorage.getItem("projectData.id");
} else { } else {
try { try {
projectToLogin = orgUserProjects[0]; projectToLogin = orgUserProjects[0];
localStorage.setItem( localStorage.setItem("projectData.id", projectToLogin);
"projectData.id",
projectToLogin
);
} catch (error) { } catch (error) {
console.log( console.log("ERROR: User likely has no projects. ", error);
"ERROR: User likely has no projects. ",
error
);
} }
} }
@@ -164,14 +144,8 @@ const attemptLogin = async (
"hgSIwDAKvz8PJfkj6xkzYqzGmAP3HLuG", "hgSIwDAKvz8PJfkj6xkzYqzGmAP3HLuG",
"shared", "shared",
], ],
WEBSITE_URL: [ WEBSITE_URL: ["http://localhost:3000", "shared"],
"http://localhost:3000", STRIPE_SECRET_KEY: ["sk_test_7348oyho4hfq398HIUOH78", "shared"],
"shared",
],
STRIPE_SECRET_KEY: [
"sk_test_7348oyho4hfq398HIUOH78",
"shared",
],
}, },
projectToLogin, projectToLogin,
"Development" "Development"
@@ -1,9 +1,11 @@
const ENV = process.env.NEXT_PUBLIC_ENV! || 'development'; // investigate const ENV = process.env.NEXT_PUBLIC_ENV! || "development"; // investigate
const POSTHOG_API_KEY = process.env.NEXT_PUBLIC_POSTHOG_API_KEY!; const POSTHOG_API_KEY = process.env.NEXT_PUBLIC_POSTHOG_API_KEY!;
const POSTHOG_HOST = process.env.NEXT_PUBLIC_POSTHOG_HOST! || 'https://app.posthog.com'; const POSTHOG_HOST =
process.env.NEXT_PUBLIC_POSTHOG_HOST! || "https://app.posthog.com";
const STRIPE_PRODUCT_PRO = process.env.NEXT_PUBLIC_STRIPE_PRODUCT_PRO!; const STRIPE_PRODUCT_PRO = process.env.NEXT_PUBLIC_STRIPE_PRODUCT_PRO!;
const STRIPE_PRODUCT_STARTER = process.env.NEXT_PUBLIC_STRIPE_PRODUCT_STARTER!; const STRIPE_PRODUCT_STARTER = process.env.NEXT_PUBLIC_STRIPE_PRODUCT_STARTER!;
const TELEMETRY_ENABLED = (process.env.NEXT_PUBLIC_TELEMETRY_ENABLED! !== 'false'); const TELEMETRY_ENABLED =
process.env.NEXT_PUBLIC_TELEMETRY_ENABLED! !== "false";
export { export {
ENV, ENV,
@@ -11,5 +13,5 @@ export {
POSTHOG_HOST, POSTHOG_HOST,
STRIPE_PRODUCT_PRO, STRIPE_PRODUCT_PRO,
STRIPE_PRODUCT_STARTER, STRIPE_PRODUCT_STARTER,
TELEMETRY_ENABLED TELEMETRY_ENABLED,
}; };
@@ -61,8 +61,7 @@ const changePassword = async (
password: newPassword, password: newPassword,
}, },
async () => { async () => {
clientNewPassword.createVerifier( clientNewPassword.createVerifier(async (err, result) => {
async (err, result) => {
// The Blob part here is needed to account for symbols that count as 2+ bytes (e.g., é, å, ø) // The Blob part here is needed to account for symbols that count as 2+ bytes (e.g., é, å, ø)
let { ciphertext, iv, tag } = Aes256Gcm.encrypt( let { ciphertext, iv, tag } = Aes256Gcm.encrypt(
localStorage.getItem("PRIVATE_KEY"), localStorage.getItem("PRIVATE_KEY"),
@@ -70,19 +69,14 @@ const changePassword = async (
.slice(0, 32) .slice(0, 32)
.padStart( .padStart(
32 + 32 +
(newPassword.slice(0, 32) (newPassword.slice(0, 32).length -
.length - new Blob([newPassword]).size),
new Blob([newPassword])
.size),
"0" "0"
) )
); );
if (ciphertext) { if (ciphertext) {
localStorage.setItem( localStorage.setItem("encryptedPrivateKey", ciphertext);
"encryptedPrivateKey",
ciphertext
);
localStorage.setItem("iv", iv); localStorage.setItem("iv", iv);
localStorage.setItem("tag", tag); localStorage.setItem("tag", tag);
@@ -108,8 +102,7 @@ const changePassword = async (
console.log(err); console.log(err);
} }
} }
} });
);
} }
); );
} }
@@ -1,8 +1,8 @@
import issueBackupPrivateKey from "~/pages/api/auth/IssueBackupPrivateKey"; import issueBackupPrivateKey from "~/pages/api/auth/IssueBackupPrivateKey";
import SRP1 from "~/pages/api/auth/SRP1"; import SRP1 from "~/pages/api/auth/SRP1";
import Aes256Gcm from "./aes-256-gcm";
import generateBackupPDF from "../generateBackupPDF"; import generateBackupPDF from "../generateBackupPDF";
import Aes256Gcm from "./aes-256-gcm";
const nacl = require("tweetnacl"); const nacl = require("tweetnacl");
nacl.util = require("tweetnacl-util"); nacl.util = require("tweetnacl-util");
@@ -80,11 +80,7 @@ const issueBackupKey = async ({
if (res.status == 400) { if (res.status == 400) {
setBackupKeyError(true); setBackupKeyError(true);
} else if (res.status == 200) { } else if (res.status == 200) {
generateBackupPDF( generateBackupPDF(personalName, email, generatedKey);
personalName,
email,
generatedKey
);
setBackupKeyIssued(true); setBackupKeyIssued(true);
} }
}); });
@@ -9,11 +9,11 @@ function generateBackupPDF(personalName, personalEmail, generatedKey) {
// new jsPDF('p', 'mm', [297, 210]); // new jsPDF('p', 'mm', [297, 210]);
var today = new Date(); var today = new Date();
var dd = String(today.getDate()).padStart(2, '0'); var dd = String(today.getDate()).padStart(2, "0");
var mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0! var mm = String(today.getMonth() + 1).padStart(2, "0"); //January is 0!
var yyyy = today.getFullYear(); var yyyy = today.getFullYear();
today = mm + '/' + dd + '/' + yyyy; today = mm + "/" + dd + "/" + yyyy;
var doc = new jsPDF("p", "pt"); var doc = new jsPDF("p", "pt");
doc.setFillColor(13, 17, 23); doc.setFillColor(13, 17, 23);
@@ -34,28 +34,16 @@ function generateBackupPDF(personalName, personalEmail, generatedKey) {
180, 180,
"In case you get locked out of you Infisical account, you`ll need these account details" "In case you get locked out of you Infisical account, you`ll need these account details"
); );
doc.text( doc.text(32, 200, "to sign in —");
32,
200,
"to sign in —"
);
doc.setFont(undefined, "bold"); doc.setFont(undefined, "bold");
doc.text( doc.text(
110, 110,
200, 200,
"including your Secret Key, which we absolutely cannot access or" "including your Secret Key, which we absolutely cannot access or"
); );
doc.text( doc.text(32, 220, "recover for you. ");
32,
220,
"recover for you. "
);
doc.setFont(undefined, "normal"); doc.setFont(undefined, "normal");
doc.text( doc.text(32, 250, "Recommendations:");
32,
250,
"Recommendations:"
);
doc.text( doc.text(
32, 32,
280, 280,
@@ -66,70 +54,33 @@ function generateBackupPDF(personalName, personalEmail, generatedKey) {
310, 310,
"2. Store it somewhere safe (such as with your birth certificate, your will, or on your" "2. Store it somewhere safe (such as with your birth certificate, your will, or on your"
); );
doc.text( doc.text(32, 330, "personal cloud storage).");
32,
330,
"personal cloud storage)."
);
doc.setFillColor(206, 217, 111); doc.setFillColor(206, 217, 111);
doc.roundedRect(32, 350, 530, 190, 5, 5, 'F'); doc.roundedRect(32, 350, 530, 190, 5, 5, "F");
doc.setDrawColor(228, 255, 0) doc.setDrawColor(228, 255, 0);
doc.setLineWidth(1) doc.setLineWidth(1);
doc.roundedRect(32, 350, 530, 190, 5, 5, 'S'); doc.roundedRect(32, 350, 530, 190, 5, 5, "S");
doc.setTextColor(43, 43, 43); doc.setTextColor(43, 43, 43);
doc.setFont(undefined, "bold"); doc.setFont(undefined, "bold");
doc.setFontSize(15); doc.setFontSize(15);
doc.text( doc.text(290, 375, "Infisical Account Details", "center");
290,
375,
"Infisical Account Details",
"center"
);
doc.setFont(undefined, "normal"); doc.setFont(undefined, "normal");
doc.setFontSize(12); doc.setFontSize(12);
doc.text( doc.text(50, 420, "SIGN-IN URL");
50, doc.text(50, 465, "EMAIL ADDRESS");
420, doc.text(50, 510, "SECRET KEY");
"SIGN-IN URL"
);
doc.text(
50,
465,
"EMAIL ADDRESS"
);
doc.text(
50,
510,
"SECRET KEY"
);
doc.setFillColor(23, 27, 33); doc.setFillColor(23, 27, 33);
doc.roundedRect(170, 398, 375, 35, 5, 5, 'F'); doc.roundedRect(170, 398, 375, 35, 5, 5, "F");
doc.roundedRect(170, 443, 375, 35, 5, 5, 'F'); doc.roundedRect(170, 443, 375, 35, 5, 5, "F");
doc.roundedRect(170, 488, 375, 35, 5, 5, 'F'); doc.roundedRect(170, 488, 375, 35, 5, 5, "F");
doc.setTextColor(227, 227, 227); doc.setTextColor(227, 227, 227);
doc.setFontSize(14); doc.setFontSize(14);
doc.text( doc.text(180, 420, "https://app.infisical.com/login");
180, doc.text(180, 465, personalEmail);
420, doc.text(180, 510, generatedKey);
"https://app.infisical.com/login" doc.text(32, 575, "Need help? Contact us at support@infisical.com");
);
doc.text(
180,
465,
personalEmail
);
doc.text(
180,
510,
generatedKey
);
doc.text(
32,
575,
"Need help? Contact us at [email protected]"
);
doc.save("Infisical Emergency Kit.pdf"); doc.save("Infisical Emergency Kit.pdf");
}; }
export default generateBackupPDF; export default generateBackupPDF;
@@ -95,9 +95,7 @@ const getSecretsForProject = async ({
line["type"], line["type"],
]); ]);
} catch (error) { } catch (error) {
console.log( console.log("Something went wrong during accessing or decripting secrets.");
"Something went wrong during accessing or decripting secrets."
);
} }
return true; return true;
}; };
@@ -69,10 +69,7 @@ const pushKeys = async (obj, workspaceId, env) => {
ciphertextValue, ciphertextValue,
ivValue, ivValue,
tagValue, tagValue,
hashValue: crypto hashValue: crypto.createHash("sha256").update(obj[key][0]).digest("hex"),
.createHash("sha256")
.update(obj[key][0])
.digest("hex"),
type: visibility, type: visibility,
}; };
}); });
@@ -2,7 +2,10 @@ import publicKeyInfical from "~/pages/api/auth/publicKeyInfisical";
import changeHerokuConfigVars from "~/pages/api/integrations/ChangeHerokuConfigVars"; import changeHerokuConfigVars from "~/pages/api/integrations/ChangeHerokuConfigVars";
const crypto = require("crypto"); const crypto = require("crypto");
const { encryptSymmetric, encryptAssymmetric } = require("../cryptography/crypto"); const {
encryptSymmetric,
encryptAssymmetric,
} = require("../cryptography/crypto");
const nacl = require("tweetnacl"); const nacl = require("tweetnacl");
nacl.util = require("tweetnacl-util"); nacl.util = require("tweetnacl-util");
@@ -42,10 +45,7 @@ const pushKeysIntegration = async ({ obj, integrationId }) => {
ciphertextValue, ciphertextValue,
ivValue, ivValue,
tagValue, tagValue,
hashValue: crypto hashValue: crypto.createHash("sha256").update(obj[key]).digest("hex"),
.createHash("sha256")
.update(obj[key])
.digest("hex"),
type: visibility, type: visibility,
}; };
}); });
+7 -3
View File
@@ -2,11 +2,15 @@
const ContentSecurityPolicy = ` const ContentSecurityPolicy = `
default-src ${process.env.NEXT_PUBLIC_WEBSITE_URL}; default-src ${process.env.NEXT_PUBLIC_WEBSITE_URL};
script-src ${process.env.NEXT_PUBLIC_WEBSITE_URL} https://app.posthog.com https://infisical.com https://assets.calendly.com/ https://js.stripe.com https://api.stripe.com 'unsafe-inline' 'unsafe-eval'; script-src ${
process.env.NEXT_PUBLIC_WEBSITE_URL
} https://app.posthog.com https://infisical.com https://assets.calendly.com/ https://js.stripe.com https://api.stripe.com 'unsafe-inline' 'unsafe-eval';
style-src 'self' https://rsms.me 'unsafe-inline'; style-src 'self' https://rsms.me 'unsafe-inline';
child-src https://infisical.com https://api.stripe.com; child-src https://infisical.com https://api.stripe.com;
frame-src https://js.stripe.com/ https://api.stripe.com; frame-src https://js.stripe.com/ https://api.stripe.com;
connect-src ws://${process.env.NEXT_PUBLIC_WEBSITE_URL?.split('//')[1]} ${process.env.NEXT_PUBLIC_WEBSITE_URL} https://api.github.com/repos/Infisical/infisical-cli https://api.heroku.com/ https://id.heroku.com/oauth/authorize https://id.heroku.com/oauth/token https://checkout.stripe.com https://app.posthog.com https://infisical.com https://api.stripe.com https://vitals.vercel-insights.com/v1/vitals; connect-src ws://${process.env.NEXT_PUBLIC_WEBSITE_URL?.split("//")[1]} ${
process.env.NEXT_PUBLIC_WEBSITE_URL
} https://api.github.com/repos/Infisical/infisical-cli https://api.heroku.com/ https://id.heroku.com/oauth/authorize https://id.heroku.com/oauth/token https://checkout.stripe.com https://app.posthog.com https://infisical.com https://api.stripe.com https://vitals.vercel-insights.com/v1/vitals;
img-src 'self' https://*.stripe.com https://i.ytimg.com/ data:; img-src 'self' https://*.stripe.com https://i.ytimg.com/ data:;
media-src; media-src;
font-src 'self' https://maxcdn.bootstrapcdn.com https://rsms.me https://fonts.gstatic.com; font-src 'self' https://maxcdn.bootstrapcdn.com https://rsms.me https://fonts.gstatic.com;
@@ -50,7 +54,7 @@ const securityHeaders = [
]; ];
module.exports = { module.exports = {
output: 'standalone', output: "standalone",
async headers() { async headers() {
return [ return [
{ {
+1 -2
View File
@@ -5,9 +5,8 @@ import { config } from "@fortawesome/fontawesome-svg-core";
import { initPostHog } from "~/components/analytics/posthog"; import { initPostHog } from "~/components/analytics/posthog";
import Layout from "~/components/basic/layout"; import Layout from "~/components/basic/layout";
import RouteGuard from "~/components/RouteGuard"; import RouteGuard from "~/components/RouteGuard";
import { ENV } from "~/utilities/config";
import { publicPaths } from "~/const"; import { publicPaths } from "~/const";
import { ENV } from "~/utilities/config";
import "@fortawesome/fontawesome-svg-core/styles.css"; import "@fortawesome/fontawesome-svg-core/styles.css";
import "../styles/globals.css"; import "../styles/globals.css";
+1 -2
View File
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This is the second step of the change password process (pake) * This is the second step of the change password process (pake)
+1 -2
View File
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient.js";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient.js";
/** /**
* This function is used to check if the user is authenticated. * This function is used to check if the user is authenticated.
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This is the route that issues a backup private key that will afterwards be added into a pdf * This is the route that issues a backup private key that will afterwards be added into a pdf
+1 -2
View File
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route logs the user out. Note: the user should authorized to do this. * This route logs the user out. Note: the user should authorized to do this.
+1 -2
View File
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This is the first step of the change password process (pake) * This is the first step of the change password process (pake)
+1 -2
View File
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient.js";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient.js";
/** /**
* This function fetches the encrypted secrets from the .env file * This function fetches the encrypted secrets from the .env file
+1 -2
View File
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This function uploads the encrypted .env file * This function uploads the encrypted .env file
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
const changeHerokuConfigVars = ({ integrationId, key, secrets }) => { const changeHerokuConfigVars = ({ integrationId, key, secrets }) => {
return SecurityClient.fetchCall( return SecurityClient.fetchCall(
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route deletes an integration from a certain project * This route deletes an integration from a certain project
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route deletes an integration authorization from a certain project * This route deletes an integration authorization from a certain project
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
const getIntegrationApps = ({ integrationAuthId }) => { const getIntegrationApps = ({ integrationAuthId }) => {
return SecurityClient.fetchCall( return SecurityClient.fetchCall(
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
const getIntegrations = () => { const getIntegrations = () => {
return SecurityClient.fetchCall(PATH + "/api/v1/integration/integrations", { return SecurityClient.fetchCall(PATH + "/api/v1/integration/integrations", {
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route starts the integration after teh default one if gonna set up. * This route starts the integration after teh default one if gonna set up.
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This is the first step of the change password process (pake) * This is the first step of the change password process (pake)
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route gets authorizations of a certain project (Heroku, etc.) * This route gets authorizations of a certain project (Heroku, etc.)
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route gets integrations of a certain project (Heroku, etc.) * This route gets integrations of a certain project (Heroku, etc.)
+1 -2
View File
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route lets us get info about a certain org * This route lets us get info about a certain org
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route lets us get all the users in an org. * This route lets us get all the users in an org.
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route lets us get the current subscription of an org. * This route lets us get the current subscription of an org.
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route lets us get all the projects of a certain user in an org. * This route lets us get all the projects of a certain user in an org.
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route lets us get all the users in an org. * This route lets us get all the users in an org.
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route redirects the user to the right stripe billing page. * This route redirects the user to the right stripe billing page.
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route add an incident contact email to a certain organization * This route add an incident contact email to a certain organization
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This function sends an email invite to a user to join an org * This function sends an email invite to a user to join an org
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route deletes an incident Contact from a certain organization * This route deletes an incident Contact from a certain organization
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This function removes a certain member from a certain organization * This function removes a certain member from a certain organization
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This routes gets all the incident contacts of a certain organization * This routes gets all the incident contacts of a certain organization
+1 -2
View File
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route lets us get the all the orgs of a certain user. * This route lets us get the all the orgs of a certain user.
+1 -2
View File
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route lets us rename a certain org. * This route lets us rename a certain org.
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route gets service tokens for a specific user in a project * This route gets service tokens for a specific user in a project
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route gets service tokens for a specific user in a project * This route gets service tokens for a specific user in a project
+1 -2
View File
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route gets the information about a specific user. * This route gets the information about a specific user.
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route registers a certain action for a user * This route registers a certain action for a user
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route registers a certain action for a user * This route registers a certain action for a user
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This function adds a user to a project * This function adds a user to a project
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This function change the access of a user in a certain workspace * This function change the access of a user in a certain workspace
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route creates a new workspace for a user. * This route creates a new workspace for a user.
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This function removes a certain member from a certain workspace * This function removes a certain member from a certain workspace
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route deletes a specified workspace. * This route deletes a specified workspace.
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* Get the latest key pairs from a certain workspace * Get the latest key pairs from a certain workspace
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route lets us get the information of a certain project. * This route lets us get the information of a certain project.
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route lets us get the public keys of everyone in your workspace. * This route lets us get the public keys of everyone in your workspace.
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route lets us get all the users in the workspace. * This route lets us get all the users in the workspace.
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route lets us get the public keys of everyone in your workspace. * This route lets us get the public keys of everyone in your workspace.
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route lets us rename a certain workspace. * This route lets us rename a certain workspace.
+1 -2
View File
@@ -1,6 +1,5 @@
import SecurityClient from "~/utilities/SecurityClient";
import { PATH } from "~/const"; import { PATH } from "~/const";
import SecurityClient from "~/utilities/SecurityClient";
/** /**
* This route uplods the keys in an encrypted format. * This route uplods the keys in an encrypted format.
+1 -3
View File
@@ -15,9 +15,7 @@ export default function DashboardRedirect() {
let userWorkspace; let userWorkspace;
try { try {
if (localStorage.getItem("projectData.id")) { if (localStorage.getItem("projectData.id")) {
router.push( router.push("/dashboard/" + localStorage.getItem("projectData.id"));
"/dashboard/" + localStorage.getItem("projectData.id")
);
} else { } else {
const userWorkspaces = await getWorkspaces(); const userWorkspaces = await getWorkspaces();
userWorkspace = userWorkspaces[0]._id; userWorkspace = userWorkspaces[0]._id;
+47 -115
View File
@@ -17,8 +17,8 @@ import {
faPeopleGroup, faPeopleGroup,
faPerson, faPerson,
faPlus, faPlus,
faShuffle,
faX, faX,
faShuffle
} from "@fortawesome/free-solid-svg-icons"; } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Menu, Transition } from "@headlessui/react"; import { Menu, Transition } from "@headlessui/react";
@@ -116,9 +116,7 @@ const KeyPair = ({
<div <div
onClick={() => onClick={() =>
modifyVisibility( modifyVisibility(
keyPair[4] == "personal" keyPair[4] == "personal" ? "shared" : "personal",
? "shared"
: "personal",
keyPair[1] keyPair[1]
) )
} }
@@ -126,16 +124,10 @@ const KeyPair = ({
> >
<FontAwesomeIcon <FontAwesomeIcon
className="text-lg pl-1.5 pr-3" className="text-lg pl-1.5 pr-3"
icon={ icon={keyPair[4] == "personal" ? faPeopleGroup : faPerson}
keyPair[4] == "personal"
? faPeopleGroup
: faPerson
}
/> />
<div className="text-sm"> <div className="text-sm">
{keyPair[4] == "personal" {keyPair[4] == "personal" ? "Make Shared" : "Make Personal"}
? "Make Shared"
: "Make Personal"}
</div> </div>
</div> </div>
<div <div
@@ -145,18 +137,19 @@ const KeyPair = ({
} else if (randomStringLength < 2) { } else if (randomStringLength < 2) {
setRandomStringLength(2); setRandomStringLength(2);
} else { } else {
modifyValue([...Array(randomStringLength)].map(() => Math.floor(Math.random() * 16).toString(16)).join(''), keyPair[1]); modifyValue(
[...Array(randomStringLength)]
.map(() => Math.floor(Math.random() * 16).toString(16))
.join(""),
keyPair[1]
);
} }
}} }}
className="relative flex flex-row 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" className="relative flex flex-row 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"
> >
<FontAwesomeIcon <FontAwesomeIcon
className="text-lg pl-1.5 pr-3" className="text-lg pl-1.5 pr-3"
icon={ icon={keyPair[3] == "" ? faPlus : faShuffle}
keyPair[3] == ""
? faPlus
: faShuffle
}
/> />
<div className="text-sm justify-between flex flex-row w-full"> <div className="text-sm justify-between flex flex-row w-full">
<p>Generate Random Hex</p> <p>Generate Random Hex</p>
@@ -168,14 +161,16 @@ const KeyPair = ({
className="m-0.5 px-1 cursor-pointer rounded-md hover:bg-chicago-700" className="m-0.5 px-1 cursor-pointer rounded-md hover:bg-chicago-700"
onClick={() => { onClick={() => {
if (randomStringLength > 1) { if (randomStringLength > 1) {
setRandomStringLength(randomStringLength - 1) setRandomStringLength(randomStringLength - 1);
} }
}} }}
> >
- -
</div> </div>
<input <input
onChange={(e) => setRandomStringLength(parseInt(e.target.value))} onChange={(e) =>
setRandomStringLength(parseInt(e.target.value))
}
value={randomStringLength} value={randomStringLength}
className="text-center z-20 peer text-sm bg-transparent w-full outline-none" className="text-center z-20 peer text-sm bg-transparent w-full outline-none"
spellCheck="false" spellCheck="false"
@@ -184,7 +179,7 @@ const KeyPair = ({
className="m-0.5 px-1 pb-0.5 cursor-pointer rounded-md hover:bg-chicago-700" className="m-0.5 px-1 pb-0.5 cursor-pointer rounded-md hover:bg-chicago-700"
onClick={() => { onClick={() => {
if (randomStringLength < 32) { if (randomStringLength < 32) {
setRandomStringLength(randomStringLength + 1) setRandomStringLength(randomStringLength + 1);
} }
}} }}
> >
@@ -280,13 +275,9 @@ export default function Dashboard() {
(async () => { (async () => {
try { try {
let userWorkspaces = await getWorkspaces(); let userWorkspaces = await getWorkspaces();
const listWorkspaces = userWorkspaces.map( const listWorkspaces = userWorkspaces.map((workspace) => workspace._id);
(workspace) => workspace._id
);
if ( if (
!listWorkspaces.includes( !listWorkspaces.includes(router.asPath.split("/")[2].split("?")[0])
router.asPath.split("/")[2].split("?")[0]
)
) { ) {
router.push("/dashboard/" + listWorkspaces[0]); router.push("/dashboard/" + listWorkspaces[0]);
} }
@@ -307,9 +298,7 @@ export default function Dashboard() {
const user = await getUser(); const user = await getUser();
setIsNew( setIsNew(
(Date.parse(new Date()) - Date.parse(user.createdAt)) / (Date.parse(new Date()) - Date.parse(user.createdAt)) / 60000 < 3
60000 <
3
? true ? true
: false : false
); );
@@ -428,9 +417,7 @@ export default function Dashboard() {
// This function downloads the secrets as a .env file // This function downloads the secrets as a .env file
const download = () => { const download = () => {
const file = data const file = data.map((item) => [item[2], item[3]].join("=")).join("\n");
.map((item) => [item[2], item[3]].join("="))
.join("\n");
const blob = new Blob([file]); const blob = new Blob([file]);
const fileDownloadUrl = URL.createObjectURL(blob); const fileDownloadUrl = URL.createObjectURL(blob);
let alink = document.createElement("a"); let alink = document.createElement("a");
@@ -464,10 +451,7 @@ export default function Dashboard() {
<title>Secrets</title> <title>Secrets</title>
<link rel="icon" href="/infisical.ico" /> <link rel="icon" href="/infisical.ico" />
<meta property="og:image" content="/images/message.png" /> <meta property="og:image" content="/images/message.png" />
<meta <meta property="og:title" content="Manage your .env files in seconds" />
property="og:title"
content="Manage your .env files in seconds"
/>
<meta <meta
name="og:description" name="og:description"
content="Infisical a simple end-to-end encrypted platform that enables teams to sync and manage their .env files." content="Infisical a simple end-to-end encrypted platform that enables teams to sync and manage their .env files."
@@ -493,12 +477,7 @@ export default function Dashboard() {
{data?.length == 0 && ( {data?.length == 0 && (
<ListBox <ListBox
selected={env} selected={env}
data={[ data={["Development", "Staging", "Production", "Testing"]}
"Development",
"Staging",
"Production",
"Testing",
]}
// ref={useRef(123)} // ref={useRef(123)}
onChange={setEnv} onChange={setEnv}
className="z-40" className="z-40"
@@ -507,9 +486,7 @@ export default function Dashboard() {
</div> </div>
<div className="flex flex-row"> <div className="flex flex-row">
<div className="flex justify-end items-center bg-white/[0.07] text-base mt-2 mr-2 rounded-md text-gray-400"> <div className="flex justify-end items-center bg-white/[0.07] text-base mt-2 mr-2 rounded-md text-gray-400">
<p className="mr-2 font-bold pl-4"> <p className="mr-2 font-bold pl-4">Project ID:</p>
Project ID:
</p>
<input <input
type="text" type="text"
value={workspaceId} value={workspaceId}
@@ -523,10 +500,7 @@ export default function Dashboard() {
className="pl-4 pr-4 border-l border-white/20 py-2 hover:bg-white/[0.12] duration-200" className="pl-4 pr-4 border-l border-white/20 py-2 hover:bg-white/[0.12] duration-200"
> >
{projectIdCopied ? ( {projectIdCopied ? (
<FontAwesomeIcon <FontAwesomeIcon icon={faCheck} className="pr-0.5" />
icon={faCheck}
className="pr-0.5"
/>
) : ( ) : (
<FontAwesomeIcon icon={faCopy} /> <FontAwesomeIcon icon={faCopy} />
)} )}
@@ -537,9 +511,7 @@ export default function Dashboard() {
</div> </div>
</div> </div>
{(data?.length !== 0 || buttonReady) && ( {(data?.length !== 0 || buttonReady) && (
<div <div className={`flex justify-start max-w-sm mt-2`}>
className={`flex justify-start max-w-sm mt-2`}
>
<Button <Button
text="Save Changes" text="Save Changes"
onButtonPressed={savePush} onButtonPressed={savePush}
@@ -560,12 +532,7 @@ export default function Dashboard() {
<> <>
<ListBox <ListBox
selected={env} selected={env}
data={[ data={["Development", "Staging", "Production", "Testing"]}
"Development",
"Staging",
"Production",
"Testing",
]}
// ref={useRef(123)} // ref={useRef(123)}
onChange={setEnv} onChange={setEnv}
className="z-40" className="z-40"
@@ -578,11 +545,7 @@ export default function Dashboard() {
<input <input
className="pl-2 text-gray-400 rounded-r-md bg-white/5 w-full h-full outline-none" className="pl-2 text-gray-400 rounded-r-md bg-white/5 w-full h-full outline-none"
value={searchKeys} value={searchKeys}
onChange={(e) => onChange={(e) => setSearchKeys(e.target.value)}
setSearchKeys(
e.target.value
)
}
placeholder={"Search keys..."} placeholder={"Search keys..."}
/> />
</div> </div>
@@ -611,9 +574,7 @@ export default function Dashboard() {
onButtonPressed={changeBlurred} onButtonPressed={changeBlurred}
color="mineshaft" color="mineshaft"
size="icon-md" size="icon-md"
icon={ icon={blurred ? faEye : faEyeSlash}
blurred ? faEye : faEyeSlash
}
/> />
</div> </div>
<div className="relative ml-2 min-w-max flex flex-row items-start justify-end"> <div className="relative ml-2 min-w-max flex flex-row items-start justify-end">
@@ -646,17 +607,14 @@ export default function Dashboard() {
<div className="rounded-t-md sticky top-0 z-20 bg-bunker flex flex-row pl-4 pr-6 pt-4 pb-2 items-center justify-between text-gray-300 font-bold"> <div className="rounded-t-md sticky top-0 z-20 bg-bunker flex flex-row pl-4 pr-6 pt-4 pb-2 items-center justify-between text-gray-300 font-bold">
{/* <FontAwesomeIcon icon={faAngleDown} /> */} {/* <FontAwesomeIcon icon={faAngleDown} /> */}
<div className="flex flex-row items-center"> <div className="flex flex-row items-center">
<p className="pl-2 text-lg"> <p className="pl-2 text-lg">Personal</p>
Personal
</p>
<div className="group font-normal group relative inline-block text-gray-300 underline hover:text-primary duration-200"> <div className="group font-normal group relative inline-block text-gray-300 underline hover:text-primary duration-200">
<FontAwesomeIcon <FontAwesomeIcon
className="ml-3 mt-1 text-lg" className="ml-3 mt-1 text-lg"
icon={faCircleInfo} icon={faCircleInfo}
/> />
<span className="absolute hidden group-hover:flex group-hover:animate-popdown duration-300 w-44 -left-16 -top-7 translate-y-full px-2 py-2 bg-gray-700 rounded-md text-center text-gray-100 text-sm after:content-[''] after:absolute after:left-1/2 after:bottom-[100%] after:-translate-x-1/2 after:border-8 after:border-x-transparent after:border-t-transparent after:border-b-gray-700"> <span className="absolute hidden group-hover:flex group-hover:animate-popdown duration-300 w-44 -left-16 -top-7 translate-y-full px-2 py-2 bg-gray-700 rounded-md text-center text-gray-100 text-sm after:content-[''] after:absolute after:left-1/2 after:bottom-[100%] after:-translate-x-1/2 after:border-8 after:border-x-transparent after:border-t-transparent after:border-b-gray-700">
Personal keys are only Personal keys are only visible to you
visible to you
</span> </span>
</div> </div>
</div> </div>
@@ -667,9 +625,7 @@ export default function Dashboard() {
(keyPair) => (keyPair) =>
keyPair[2] keyPair[2]
.toLowerCase() .toLowerCase()
.includes( .includes(searchKeys.toLowerCase()) &&
searchKeys.toLowerCase()
) &&
keyPair[4] == "personal" keyPair[4] == "personal"
) )
.sort((a, b) => .sort((a, b) =>
@@ -682,13 +638,9 @@ export default function Dashboard() {
key={keyPair[0]} key={keyPair[0]}
keyPair={keyPair} keyPair={keyPair}
deleteRow={deleteCertainRow} deleteRow={deleteCertainRow}
modifyValue={ modifyValue={listenChangeValue}
listenChangeValue
}
modifyKey={listenChangeKey} modifyKey={listenChangeKey}
modifyVisibility={ modifyVisibility={listenChangeVisibility}
listenChangeVisibility
}
isBlurred={blurred} isBlurred={blurred}
/> />
))} ))}
@@ -702,17 +654,14 @@ export default function Dashboard() {
<div className="sticky top-0 z-40 bg-bunker flex flex-row pl-4 pr-5 pt-4 pb-2 items-center justify-between text-gray-300 font-bold"> <div className="sticky top-0 z-40 bg-bunker flex flex-row pl-4 pr-5 pt-4 pb-2 items-center justify-between text-gray-300 font-bold">
{/* <FontAwesomeIcon icon={faAngleDown} /> */} {/* <FontAwesomeIcon icon={faAngleDown} /> */}
<div className="flex flex-row items-center"> <div className="flex flex-row items-center">
<p className="pl-2 text-lg"> <p className="pl-2 text-lg">Shared</p>
Shared
</p>
<div className="group font-normal group relative inline-block text-gray-300 underline hover:text-primary duration-200"> <div className="group font-normal group relative inline-block text-gray-300 underline hover:text-primary duration-200">
<FontAwesomeIcon <FontAwesomeIcon
className="ml-3 text-lg mt-1" className="ml-3 text-lg mt-1"
icon={faCircleInfo} icon={faCircleInfo}
/> />
<span className="absolute hidden group-hover:flex group-hover:animate-popdown duration-300 w-44 -left-16 -top-7 translate-y-full px-2 py-2 bg-gray-700 rounded-md text-center text-gray-100 text-sm after:content-[''] after:absolute after:left-1/2 after:bottom-[100%] after:-translate-x-1/2 after:border-8 after:border-x-transparent after:border-t-transparent after:border-b-gray-700"> <span className="absolute hidden group-hover:flex group-hover:animate-popdown duration-300 w-44 -left-16 -top-7 translate-y-full px-2 py-2 bg-gray-700 rounded-md text-center text-gray-100 text-sm after:content-[''] after:absolute after:left-1/2 after:bottom-[100%] after:-translate-x-1/2 after:border-8 after:border-x-transparent after:border-t-transparent after:border-b-gray-700">
Shared keys are visible to Shared keys are visible to your whole team
your whole team
</span> </span>
</div> </div>
</div> </div>
@@ -723,9 +672,7 @@ export default function Dashboard() {
(keyPair) => (keyPair) =>
keyPair[2] keyPair[2]
.toLowerCase() .toLowerCase()
.includes( .includes(searchKeys.toLowerCase()) &&
searchKeys.toLowerCase()
) &&
keyPair[4] == "shared" keyPair[4] == "shared"
) )
.sort((a, b) => .sort((a, b) =>
@@ -738,13 +685,9 @@ export default function Dashboard() {
key={keyPair[0]} key={keyPair[0]}
keyPair={keyPair} keyPair={keyPair}
deleteRow={deleteCertainRow} deleteRow={deleteCertainRow}
modifyValue={ modifyValue={listenChangeValue}
listenChangeValue
}
modifyKey={listenChangeKey} modifyKey={listenChangeKey}
modifyVisibility={ modifyVisibility={listenChangeVisibility}
listenChangeVisibility
}
isBlurred={blurred} isBlurred={blurred}
/> />
))} ))}
@@ -753,9 +696,7 @@ export default function Dashboard() {
<div className="w-full max-w-5xl"> <div className="w-full max-w-5xl">
<DropZone <DropZone
setData={addData} setData={addData}
setErrorDragAndDrop={ setErrorDragAndDrop={setErrorDragAndDrop}
setErrorDragAndDrop
}
createNewFile={addRow} createNewFile={addRow}
errorDragAndDrop={errorDragAndDrop} errorDragAndDrop={errorDragAndDrop}
setButtonReady={setButtonReady} setButtonReady={setButtonReady}
@@ -766,23 +707,19 @@ export default function Dashboard() {
</div> </div>
) : ( ) : (
<div className="flex flex-col items-center justify-center h-full text-xl text-gray-400 max-w-5xl mt-28"> <div className="flex flex-col items-center justify-center h-full text-xl text-gray-400 max-w-5xl mt-28">
{fileState.message != {fileState.message != "There's nothing to pull" &&
"There's nothing to pull" &&
fileState.message != undefined && ( fileState.message != undefined && (
<FontAwesomeIcon <FontAwesomeIcon
className="text-7xl mb-8" className="text-7xl mb-8"
icon={faFolderOpen} icon={faFolderOpen}
/> />
)} )}
{(fileState.message == {(fileState.message == "There's nothing to pull" ||
"There's nothing to pull" ||
fileState.message == undefined) && fileState.message == undefined) &&
isKeyAvailable && ( isKeyAvailable && (
<DropZone <DropZone
setData={setData} setData={setData}
setErrorDragAndDrop={ setErrorDragAndDrop={setErrorDragAndDrop}
setErrorDragAndDrop
}
createNewFile={addRow} createNewFile={addRow}
errorDragAndDrop={errorDragAndDrop} errorDragAndDrop={errorDragAndDrop}
setButtonReady={setButtonReady} setButtonReady={setButtonReady}
@@ -791,13 +728,9 @@ export default function Dashboard() {
)} )}
{fileState.message == {fileState.message ==
"Failed membership validation for workspace" && ( "Failed membership validation for workspace" && (
<p> <p>You are not authorized to view this project.</p>
You are not authorized to view this
project.
</p>
)} )}
{fileState.message == {fileState.message == "Access needed to pull the latest file" ||
"Access needed to pull the latest file" ||
(!isKeyAvailable && ( (!isKeyAvailable && (
<> <>
<FontAwesomeIcon <FontAwesomeIcon
@@ -805,12 +738,11 @@ export default function Dashboard() {
icon={faFolderOpen} icon={faFolderOpen}
/> />
<p> <p>
To view this file, contact your To view this file, contact your administrator for
administrator for permission. permission.
</p> </p>
<p className="mt-1"> <p className="mt-1">
They need to grant you access in They need to grant you access in the team tab.
the team tab.
</p> </p>
</> </>
))} ))}
+1 -3
View File
@@ -22,9 +22,7 @@ export default function Heroku() {
code, code,
integration: "heroku", integration: "heroku",
}); });
router.push( router.push("/integrations/" + localStorage.getItem("projectData.id"));
"/integrations/" + localStorage.getItem("projectData.id")
);
} }
} catch (error) { } catch (error) {
console.log("Error - Not logged in yet"); console.log("Error - Not logged in yet");
+40 -103
View File
@@ -1,4 +1,4 @@
import React, { useEffect,useState } from "react"; import React, { useEffect, useState } from "react";
import Head from "next/head"; import Head from "next/head";
import Image from "next/image"; import Image from "next/image";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
@@ -61,9 +61,7 @@ const Integration = ({ projectIntegration }) => {
const tempHerokuAppNames = tempHerokuApps.map((app) => app.name); const tempHerokuAppNames = tempHerokuApps.map((app) => app.name);
setApps(tempHerokuAppNames); setApps(tempHerokuAppNames);
setIntegrationApp( setIntegrationApp(
projectIntegration.app projectIntegration.app ? projectIntegration.app : tempHerokuAppNames[0]
? projectIntegration.app
: tempHerokuAppNames[0]
); );
}, []); }, []);
@@ -96,9 +94,7 @@ const Integration = ({ projectIntegration }) => {
INTEGRATION INTEGRATION
</div> </div>
<div className="py-2.5 bg-white/[.07] rounded-md pl-4 pr-20 text-sm font-semibold text-gray-300"> <div className="py-2.5 bg-white/[.07] rounded-md pl-4 pr-20 text-sm font-semibold text-gray-300">
{projectIntegration.integration {projectIntegration.integration.charAt(0).toUpperCase() +
.charAt(0)
.toUpperCase() +
projectIntegration.integration.slice(1)} projectIntegration.integration.slice(1)}
</div> </div>
</div> </div>
@@ -120,9 +116,7 @@ const Integration = ({ projectIntegration }) => {
icon={faRotate} icon={faRotate}
className="text-lg mr-2.5 text-primary animate-spin" className="text-lg mr-2.5 text-primary animate-spin"
/> />
<div className="text-gray-300 font-semibold"> <div className="text-gray-300 font-semibold">In Sync</div>
In Sync
</div>
</div> </div>
) : ( ) : (
<Button <Button
@@ -130,13 +124,11 @@ const Integration = ({ projectIntegration }) => {
onButtonPressed={async () => { onButtonPressed={async () => {
const result = await startIntegration({ const result = await startIntegration({
integrationId: projectIntegration._id, integrationId: projectIntegration._id,
environment: environment: envMapping[integrationEnvironment],
envMapping[integrationEnvironment],
appName: integrationApp, appName: integrationApp,
}); });
if (result?.status == 200) { if (result?.status == 200) {
let currentSecrets = let currentSecrets = await getSecretsForProject({
await getSecretsForProject({
env: integrationEnvironment, env: integrationEnvironment,
setFileState, setFileState,
setIsKeyAvailable, setIsKeyAvailable,
@@ -216,10 +208,7 @@ export default function Integrations() {
<title>Dashboard</title> <title>Dashboard</title>
<link rel="icon" href="/infisical.ico" /> <link rel="icon" href="/infisical.ico" />
<meta property="og:image" content="/images/message.png" /> <meta property="og:image" content="/images/message.png" />
<meta <meta property="og:title" content="Manage your .env files in seconds" />
property="og:title"
content="Manage your .env files in seconds"
/>
<meta <meta
name="og:description" name="og:description"
content="Infisical a simple end-to-end encrypted platform that enables teams to sync and manage their .env files." content="Infisical a simple end-to-end encrypted platform that enables teams to sync and manage their .env files."
@@ -227,19 +216,13 @@ export default function Integrations() {
</Head> </Head>
<div className="flex flex-row"> <div className="flex flex-row">
<div className="w-full max-h-96 pb-2 h-screen max-h-[calc(100vh-10px)] overflow-y-scroll no-scrollbar no-scrollbar::-webkit-scrollbar"> <div className="w-full max-h-96 pb-2 h-screen max-h-[calc(100vh-10px)] overflow-y-scroll no-scrollbar no-scrollbar::-webkit-scrollbar">
<NavHeader <NavHeader pageName="Project Integrations" isProjectRelated={true} />
pageName="Project Integrations"
isProjectRelated={true}
/>
<div className="flex flex-col justify-between items-start mx-4 mt-6 mb-4 text-xl max-w-5xl px-2"> <div className="flex flex-col justify-between items-start mx-4 mt-6 mb-4 text-xl max-w-5xl px-2">
<div className="flex flex-row justify-start items-center text-3xl"> <div className="flex flex-row justify-start items-center text-3xl">
<p className="font-semibold mr-4"> <p className="font-semibold mr-4">Current Project Integrations</p>
Current Project Integrations
</p>
</div> </div>
<p className="mr-4 text-base text-gray-400"> <p className="mr-4 text-base text-gray-400">
Manage your integrations of Infisical with Manage your integrations of Infisical with third-party services.
third-party services.
</p> </p>
</div> </div>
{projectIntegrations.length > 0 ? ( {projectIntegrations.length > 0 ? (
@@ -253,46 +236,40 @@ export default function Integrations() {
<div className="flex flex-col max-w-5xl justify-center bg-white/5 p-6 rounded-md mx-6 mt-8"> <div className="flex flex-col max-w-5xl justify-center bg-white/5 p-6 rounded-md mx-6 mt-8">
<div className="relative px-4 flex flex-col text-gray-400 items-center justify-center"> <div className="relative px-4 flex flex-col text-gray-400 items-center justify-center">
<div className="mb-1"> <div className="mb-1">
You {"don't"} have any integrations set up You {"don't"} have any integrations set up yet. When you do,
yet. When you do, they will appear here. they will appear here.
</div> </div>
<div className=""> <div className="">
To start, click on any of the options below. To start, click on any of the options below. It takes 5 clicks
It takes 5 clicks to set up. to set up.
</div> </div>
</div> </div>
</div> </div>
)} )}
<div className="flex flex-col justify-between items-start mx-4 mt-12 mb-4 text-xl max-w-5xl px-2"> <div className="flex flex-col justify-between items-start mx-4 mt-12 mb-4 text-xl max-w-5xl px-2">
<div className="flex flex-row justify-start items-center text-3xl"> <div className="flex flex-row justify-start items-center text-3xl">
<p className="font-semibold mr-4"> <p className="font-semibold mr-4">Available Integrations</p>
Available Integrations
</p>
</div> </div>
<p className="mr-4 text-base text-gray-400"> <p className="mr-4 text-base text-gray-400">
Click on the itegration you want to connect. This Click on the itegration you want to connect. This will let your
will let your environment variables flow environment variables flow automatically into selected third-party
automatically into selected third-party services. services.
</p> </p>
<p className="mr-4 text-xs text-gray-600 mt-1"> <p className="mr-4 text-xs text-gray-600 mt-1">
Note: during an integration with Heroku, for Note: during an integration with Heroku, for security reasons, it
security reasons, it is impossible to maintain is impossible to maintain end-to-end encryption. In theory, this
end-to-end encryption. In theory, this lets lets Infisical decrypt yor environment variables. In practice, we
Infisical decrypt yor environment variables. In can assure you that this will never be done, and it allows us to
practice, we can assure you that this will never be protect your secrets from bad actors online. The core Infisical
done, and it allows us to protect your secrets from service will always stay end-to-end encrypted. With any questions,
bad actors online. The core Infisical service will reach out support@infisical.com.
always stay end-to-end encrypted. With any
questions, reach out support@infisical.com.
</p> </p>
</div> </div>
<div className="grid gap-4 grid-cols-3 grid-rows-3 mx-6 mt-4 max-w-5xl"> <div className="grid gap-4 grid-cols-3 grid-rows-3 mx-6 mt-4 max-w-5xl">
{Object.keys(integrations).map((integration) => ( {Object.keys(integrations).map((integration) => (
<div <div
className={`relative ${ className={`relative ${
["Heroku"].includes( ["Heroku"].includes(integrations[integration].name)
integrations[integration].name
)
? "" ? ""
: "opacity-50" : "opacity-50"
}`} }`}
@@ -300,17 +277,13 @@ export default function Integrations() {
> >
<a <a
href={`${ href={`${
["Heroku"].includes( ["Heroku"].includes(integrations[integration].name)
integrations[integration].name
)
? `https://id.heroku.com/oauth/authorize?client_id=bc132901-935a-4590-b010-f1857efc380d&response_type=code&scope=write-protected&state=${csrfToken}` ? `https://id.heroku.com/oauth/authorize?client_id=bc132901-935a-4590-b010-f1857efc380d&response_type=code&scope=write-protected&state=${csrfToken}`
: "#" : "#"
}`} }`}
rel="noopener" rel="noopener"
className={`relative flex flex-row bg-white/5 h-32 rounded-md p-4 items-center ${ className={`relative flex flex-row bg-white/5 h-32 rounded-md p-4 items-center ${
["Heroku"].includes( ["Heroku"].includes(integrations[integration].name)
integrations[integration].name
)
? "hover:bg-white/10 duration-200 cursor-pointer" ? "hover:bg-white/10 duration-200 cursor-pointer"
: "cursor-default grayscale" : "cursor-default grayscale"
}`} }`}
@@ -321,27 +294,12 @@ export default function Integrations() {
width={100} width={100}
alt="integration logo" alt="integration logo"
></Image> ></Image>
{integrations[integration].name.split(" ") {integrations[integration].name.split(" ").length > 2 ? (
.length > 2 ? (
<div className="font-semibold text-gray-300 group-hover:text-gray-200 duration-200 text-3xl ml-8 max-w-xs"> <div className="font-semibold text-gray-300 group-hover:text-gray-200 duration-200 text-3xl ml-8 max-w-xs">
<div> <div>{integrations[integration].name.split(" ")[0]}</div>
{
integrations[
integration
].name.split(" ")[0]
}
</div>
<div className="text-base"> <div className="text-base">
{ {integrations[integration].name.split(" ")[1]}{" "}
integrations[ {integrations[integration].name.split(" ")[2]}
integration
].name.split(" ")[1]
}{" "}
{
integrations[
integration
].name.split(" ")[2]
}
</div> </div>
</div> </div>
) : ( ) : (
@@ -350,40 +308,21 @@ export default function Integrations() {
</div> </div>
)} )}
</a> </a>
{["Heroku"].includes( {["Heroku"].includes(integrations[integration].name) &&
integrations[integration].name
) &&
authorizations authorizations
.map( .map((authorization) => authorization.integration)
(authorization) => .includes(integrations[integration].name.toLowerCase()) && (
authorization.integration
)
.includes(
integrations[
integration
].name.toLowerCase()
) && (
<div className="absolute group z-50 top-0 right-0 flex flex-row"> <div className="absolute group z-50 top-0 right-0 flex flex-row">
<div <div
onClick={() => { onClick={() => {
deleteIntegrationAuth({ deleteIntegrationAuth({
integrationAuthId: integrationAuthId: authorizations
authorizations
.filter( .filter(
( (authorization) =>
authorization
) =>
authorization.integration == authorization.integration ==
integrations[ integrations[integration].name.toLowerCase()
integration
].name.toLowerCase()
) )
.map( .map((authorization) => authorization._id)[0],
(
authorization
) =>
authorization._id
)[0],
}); });
router.reload(); router.reload();
}} }}
@@ -404,9 +343,7 @@ export default function Integrations() {
</div> </div>
</div> </div>
)} )}
{!["Heroku"].includes( {!["Heroku"].includes(integrations[integration].name) && (
integrations[integration].name
) && (
<div className="absolute group z-50 top-0 right-0 flex flex-row"> <div className="absolute group z-50 top-0 right-0 flex flex-row">
<div className="w-max bg-yellow py-0.5 px-2 rounded-bl-md rounded-tr-md text-xs flex flex-row items-center text-black opacity-90"> <div className="w-max bg-yellow py-0.5 px-2 rounded-bl-md rounded-tr-md text-xs flex flex-row items-center text-black opacity-90">
Coming Soon Coming Soon
+5 -11
View File
@@ -1,4 +1,4 @@
import React, { useEffect,useState } from "react"; import React, { useEffect, useState } from "react";
import Head from "next/head"; import Head from "next/head";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
@@ -110,9 +110,7 @@ export default function Login() {
isRequired isRequired
/> />
</div> </div>
{errorLogin && ( {errorLogin && <Error text="Your email and/or password are wrong." />}
<Error text="Your email and/or password are wrong." />
)}
<div className="flex flex-col items-center justify-center w-full md:p-2 max-h-20 max-w-md mt-4 mx-auto text-sm"> <div className="flex flex-col items-center justify-center w-full md:p-2 max-h-20 max-w-md mt-4 mx-auto text-sm">
<div className="text-l mt-6 m-8 px-8 py-3 text-lg"> <div className="text-l mt-6 m-8 px-8 py-3 text-lg">
<Button <Button
@@ -129,13 +127,9 @@ export default function Login() {
</div> </div>
{false && ( {false && (
<div className="w-full p-2 flex flex-row items-center bg-white/10 text-gray-300 rounded-md max-w-md mx-auto mt-4"> <div className="w-full p-2 flex flex-row items-center bg-white/10 text-gray-300 rounded-md max-w-md mx-auto mt-4">
<FontAwesomeIcon <FontAwesomeIcon icon={faWarning} className="ml-2 mr-6 text-6xl" />
icon={faWarning} We are experiencing minor technical difficulties. We are working on
className="ml-2 mr-6 text-6xl" solving it right now. Please come back in a few minutes.
/>
We are experiencing minor technical difficulties. We are
working on solving it right now. Please come back in a few
minutes.
</div> </div>
)} )}
</div> </div>
+8 -4
View File
@@ -5,13 +5,17 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
export default function NoProjects() { export default function NoProjects() {
return ( return (
<div className="h-full flex flex-col items-center justify-center text-gray-300 text-lg text-center w-11/12 mr-auto"> <div className="h-full flex flex-col items-center justify-center text-gray-300 text-lg text-center w-11/12 mr-auto">
<FontAwesomeIcon icon={faFolderOpen} className="text-7xl mb-8 w-full px-auto" /> <FontAwesomeIcon
icon={faFolderOpen}
className="text-7xl mb-8 w-full px-auto"
/>
<div className="max-w-md"> <div className="max-w-md">
You are not part of any projects in this organization yet. When you do, they will appear here. You are not part of any projects in this organization yet. When you do,
they will appear here.
</div> </div>
<div className="max-w-md mt-4"> <div className="max-w-md mt-4">
Create a new project, or ask Create a new project, or ask other organization members to give you
other organization members to give you neccessary permissions. neccessary permissions.
</div> </div>
</div> </div>
); );
+2 -2
View File
@@ -13,8 +13,8 @@ export default function Activity() {
<p className="mt-2 mb-1 text-xl">Your invite has expired. </p> <p className="mt-2 mb-1 text-xl">Your invite has expired. </p>
<p className="text-xl">Ask the administrator for a new one.</p> <p className="text-xl">Ask the administrator for a new one.</p>
<p className="text-md mt-8 text-gray-600 max-w-sm text-center"> <p className="text-md mt-8 text-gray-600 max-w-sm text-center">
Note: If it still {"doesn't work"}, please reach out to us Note: If it still {"doesn't work"}, please reach out to us at
at support@infisical.com support@infisical.com
</p> </p>
</div> </div>
</div> </div>
+2 -3
View File
@@ -1,4 +1,4 @@
import React, { useEffect,useState } from "react"; import React, { useEffect, useState } from "react";
import Head from "next/head"; import Head from "next/head";
import Plan from "~/components/billing/Plan"; import Plan from "~/components/billing/Plan";
@@ -73,8 +73,7 @@ export default function SettingsBilling() {
Usage & Billing Usage & Billing
</p> </p>
<p className="font-normal mr-4 text-gray-400 text-base"> <p className="font-normal mr-4 text-gray-400 text-base">
View and manage your {"organization's"}{" "} View and manage your {"organization's"} subscription here.
subscription here.
</p> </p>
</div> </div>
</div> </div>
+18 -45
View File
@@ -1,4 +1,4 @@
import React, { useEffect,useState } from "react"; import React, { useEffect, useState } from "react";
import Head from "next/head"; import Head from "next/head";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { import {
@@ -33,8 +33,7 @@ export default function SettingsOrg() {
const router = useRouter(); const router = useRouter();
const [orgName, setOrgName] = useState(""); const [orgName, setOrgName] = useState("");
const [emailUser, setEmailUser] = useState(""); const [emailUser, setEmailUser] = useState("");
const [workspaceToBeDeletedName, setWorkspaceToBeDeletedName] = const [workspaceToBeDeletedName, setWorkspaceToBeDeletedName] = useState("");
useState("");
const [searchUsers, setSearchUsers] = useState(""); const [searchUsers, setSearchUsers] = useState("");
const [workspaceId, setWorkspaceId] = useState(""); const [workspaceId, setWorkspaceId] = useState("");
const [isAddIncidentContactOpen, setIsAddIncidentContactOpen] = const [isAddIncidentContactOpen, setIsAddIncidentContactOpen] =
@@ -60,9 +59,7 @@ export default function SettingsOrg() {
localStorage.getItem("orgData.id") localStorage.getItem("orgData.id")
); );
setIncidentContacts( setIncidentContacts(incidentContactsData?.map((contact) => contact.email));
incidentContactsData?.map((contact) => contact.email)
);
const user = await getUser(); const user = await getUser();
setPersonalEmail(user.email); setPersonalEmail(user.email);
@@ -76,10 +73,7 @@ export default function SettingsOrg() {
key: guidGenerator(), key: guidGenerator(),
firstName: user.user?.firstName, firstName: user.user?.firstName,
lastName: user.user?.lastName, lastName: user.user?.lastName,
email: email: user.user?.email == null ? user.inviteEmail : user.user?.email,
user.user?.email == null
? user.inviteEmail
: user.user?.email,
role: user?.role, role: user?.role,
status: user?.status, status: user?.status,
userId: user.user?._id, userId: user.user?._id,
@@ -134,10 +128,7 @@ export default function SettingsOrg() {
setIncidentContacts( setIncidentContacts(
incidentContacts.filter((contact) => contact != incidentContact) incidentContacts.filter((contact) => contact != incidentContact)
); );
deleteIncidentContact( deleteIncidentContact(localStorage.getItem("orgData.id"), incidentContact);
localStorage.getItem("orgData.id"),
incidentContact
);
}; };
/** /**
@@ -206,14 +197,10 @@ export default function SettingsOrg() {
/> />
</div> </div>
<div className="flex justify-start w-full"> <div className="flex justify-start w-full">
<div <div className={`flex justify-start max-w-sm mt-4 mb-2`}>
className={`flex justify-start max-w-sm mt-4 mb-2`}
>
<Button <Button
text="Save Changes" text="Save Changes"
onButtonPressed={() => onButtonPressed={() => submitChanges(orgName)}
submitChanges(orgName)
}
color="mineshaft" color="mineshaft"
size="md" size="md"
active={buttonReady} active={buttonReady}
@@ -230,8 +217,8 @@ export default function SettingsOrg() {
Organization Members Organization Members
</p> </p>
<p className="mr-4 text-gray-400 mt-2 mb-2"> <p className="mr-4 text-gray-400 mt-2 mb-2">
Manage members of your organization. These users Manage members of your organization. These users could
could afterwards be formed into projects. afterwards be formed into projects.
</p> </p>
<AddUserDialog <AddUserDialog
isOpen={isAddUserOpen} isOpen={isAddUserOpen}
@@ -253,9 +240,7 @@ export default function SettingsOrg() {
<input <input
className="pl-2 text-gray-400 rounded-r-md bg-white/5 w-full h-full outline-none" className="pl-2 text-gray-400 rounded-r-md bg-white/5 w-full h-full outline-none"
value={searchUsers} value={searchUsers}
onChange={(e) => onChange={(e) => setSearchUsers(e.target.value)}
setSearchUsers(e.target.value)
}
placeholder={"Search members..."} placeholder={"Search members..."}
/> />
</div> </div>
@@ -294,16 +279,14 @@ export default function SettingsOrg() {
Incident Contacts Incident Contacts
</p> </p>
<p className="text-xs text-gray-500 mb-2 min-w-max"> <p className="text-xs text-gray-500 mb-2 min-w-max">
These contacts will be notified in the These contacts will be notified in the unlikely event of a
unlikely event of a severe incident. severe incident.
</p> </p>
</div> </div>
<div className="mt-4 mb-2 min-w-max flex flex-row items-end justify-end justify-center"> <div className="mt-4 mb-2 min-w-max flex flex-row items-end justify-end justify-center">
<Button <Button
text="Add Contact" text="Add Contact"
onButtonPressed={ onButtonPressed={openAddIncidentContactModal}
openAddIncidentContactModal
}
color="mineshaft" color="mineshaft"
size="md" size="md"
icon={faPlus} icon={faPlus}
@@ -318,9 +301,7 @@ export default function SettingsOrg() {
<input <input
className="pl-2 text-gray-400 rounded-tr-md bg-white/5 w-full h-full outline-none" className="pl-2 text-gray-400 rounded-tr-md bg-white/5 w-full h-full outline-none"
value={searchIncidentContact} value={searchIncidentContact}
onChange={(e) => onChange={(e) => setSearchIncidentContact(e.target.value)}
setSearchIncidentContact(e.target.value)
}
placeholder={"Search..."} placeholder={"Search..."}
/> />
</div> </div>
@@ -328,23 +309,17 @@ export default function SettingsOrg() {
email.includes(searchIncidentContact) email.includes(searchIncidentContact)
).length > 0 ? ( ).length > 0 ? (
incidentContacts incidentContacts
.filter((email) => .filter((email) => email.includes(searchIncidentContact))
email.includes(searchIncidentContact)
)
.map((contact) => ( .map((contact) => (
<div <div
key={guidGenerator()} key={guidGenerator()}
className="flex flex-row items-center justify-between max-w-5xl px-4 py-3 hover:bg-white/5 border-t border-gray-600 w-full" className="flex flex-row items-center justify-between max-w-5xl px-4 py-3 hover:bg-white/5 border-t border-gray-600 w-full"
> >
<p className="text-gray-300"> <p className="text-gray-300">{contact}</p>
{contact}
</p>
<div className="opacity-50 hover:opacity-100 duration-200"> <div className="opacity-50 hover:opacity-100 duration-200">
<Button <Button
onButtonPressed={() => onButtonPressed={() =>
deleteIncidentContactFully( deleteIncidentContactFully(contact)
contact
)
} }
color="red" color="red"
size="icon-sm" size="icon-sm"
@@ -355,9 +330,7 @@ export default function SettingsOrg() {
)) ))
) : ( ) : (
<div className="w-full flex flex-row justify-center mt-6 max-w-4xl ml-6"> <div className="w-full flex flex-row justify-center mt-6 max-w-4xl ml-6">
<p className="text-gray-400"> <p className="text-gray-400">No incident contacts found.</p>
No incident contacts found.
</p>
</div> </div>
)} )}
</div> </div>
+12 -27
View File
@@ -1,4 +1,4 @@
import React, { useEffect,useState } from "react"; import React, { useEffect, useState } from "react";
import Head from "next/head"; import Head from "next/head";
import { faCheck, faX } from "@fortawesome/free-solid-svg-icons"; import { faCheck, faX } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
@@ -7,8 +7,8 @@ import Button from "~/components/basic/buttons/Button";
import InputField from "~/components/basic/InputField"; import InputField from "~/components/basic/InputField";
import NavHeader from "~/components/navigation/NavHeader"; import NavHeader from "~/components/navigation/NavHeader";
import changePassword from "~/components/utilities/cryptography/changePassword"; import changePassword from "~/components/utilities/cryptography/changePassword";
import passwordCheck from "~/utilities/checks/PasswordCheck";
import issueBackupKey from "~/components/utilities/cryptography/issueBackupKey"; import issueBackupKey from "~/components/utilities/cryptography/issueBackupKey";
import passwordCheck from "~/utilities/checks/PasswordCheck";
import getUser from "../../api/user/getUser"; import getUser from "../../api/user/getUser";
@@ -40,10 +40,7 @@ export default function PersonalSettings() {
</Head> </Head>
<div className="flex flex-row"> <div className="flex flex-row">
<div className="w-full max-h-screen pb-2 overflow-y-auto"> <div className="w-full max-h-screen pb-2 overflow-y-auto">
<NavHeader <NavHeader pageName="Personal Settings" isProjectRelated={false} />
pageName="Personal Settings"
isProjectRelated={false}
/>
<div className="flex flex-row justify-between items-center ml-6 mt-8 mb-6 text-xl max-w-5xl"> <div className="flex flex-row justify-between items-center ml-6 mt-8 mb-6 text-xl max-w-5xl">
<div className="flex flex-col justify-start items-start text-3xl"> <div className="flex flex-col justify-start items-start text-3xl">
<p className="font-semibold mr-4 text-gray-200"> <p className="font-semibold mr-4 text-gray-200">
@@ -150,9 +147,7 @@ export default function PersonalSettings() {
passwordErrorLowerCase || passwordErrorLowerCase ||
passwordErrorNumber ? ( passwordErrorNumber ? (
<div className="w-full mt-3 bg-white/5 px-2 flex flex-col items-start py-2 rounded-md max-w-xl mb-2"> <div className="w-full mt-3 bg-white/5 px-2 flex flex-col items-start py-2 rounded-md max-w-xl mb-2">
<div <div className={`text-gray-400 text-sm mb-1`}>
className={`text-gray-400 text-sm mb-1`}
>
Password should contain at least: Password should contain at least:
</div> </div>
<div className="flex flex-row justify-start items-center ml-1"> <div className="flex flex-row justify-start items-center ml-1">
@@ -169,9 +164,7 @@ export default function PersonalSettings() {
)} )}
<div <div
className={`${ className={`${
passwordErrorLength passwordErrorLength ? "text-gray-400" : "text-gray-600"
? "text-gray-400"
: "text-gray-600"
} text-sm`} } text-sm`}
> >
14 characters 14 characters
@@ -213,9 +206,7 @@ export default function PersonalSettings() {
)} )}
<div <div
className={`${ className={`${
passwordErrorNumber passwordErrorNumber ? "text-gray-400" : "text-gray-600"
? "text-gray-400"
: "text-gray-600"
} text-sm`} } text-sm`}
> >
1 number 1 number
@@ -261,9 +252,7 @@ export default function PersonalSettings() {
<FontAwesomeIcon <FontAwesomeIcon
icon={faCheck} icon={faCheck}
className={`ml-4 text-primary text-3xl ${ className={`ml-4 text-primary text-3xl ${
passwordChanged passwordChanged ? "opacity-100" : "opacity-0"
? "opacity-100"
: "opacity-0"
} duration-300`} } duration-300`}
/> />
</div> </div>
@@ -276,14 +265,12 @@ export default function PersonalSettings() {
Emergency Kit Emergency Kit
</p> </p>
<p className="text-sm text-mineshaft-300 min-w-max"> <p className="text-sm text-mineshaft-300 min-w-max">
Your Emergency Kit contains the Your Emergency Kit contains the information you’ll need to
information you’ll need to sign in to sign in to your Infisical account.
your Infisical account.
</p> </p>
<p className="text-sm text-mineshaft-300 mb-5 min-w-max"> <p className="text-sm text-mineshaft-300 mb-5 min-w-max">
Only the latest issued Emergency Kit Only the latest issued Emergency Kit remains valid. To get a
remains valid. To get a new Emergency new Emergency Kit, verify your password.
Kit, verify your password.
</p> </p>
</div> </div>
</div> </div>
@@ -318,9 +305,7 @@ export default function PersonalSettings() {
<FontAwesomeIcon <FontAwesomeIcon
icon={faCheck} icon={faCheck}
className={`ml-4 text-primary text-3xl ${ className={`ml-4 text-primary text-3xl ${
backupKeyIssued backupKeyIssued ? "opacity-100" : "opacity-0"
? "opacity-100"
: "opacity-0"
} duration-300`} } duration-300`}
/> />
</div> </div>
+24 -50
View File
@@ -1,4 +1,4 @@
import React, { useEffect,useRef, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
import Head from "next/head"; import Head from "next/head";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { faCheck, faPlus } from "@fortawesome/free-solid-svg-icons"; import { faCheck, faPlus } from "@fortawesome/free-solid-svg-icons";
@@ -19,8 +19,7 @@ export default function SettingsBasic() {
const router = useRouter(); const router = useRouter();
const [workspaceName, setWorkspaceName] = useState(""); const [workspaceName, setWorkspaceName] = useState("");
const [serviceTokens, setServiceTokens] = useState([]); const [serviceTokens, setServiceTokens] = useState([]);
const [workspaceToBeDeletedName, setWorkspaceToBeDeletedName] = const [workspaceToBeDeletedName, setWorkspaceToBeDeletedName] = useState("");
useState("");
const [workspaceId, setWorkspaceId] = useState(""); const [workspaceId, setWorkspaceId] = useState("");
const [isAddOpen, setIsAddOpen] = useState(false); const [isAddOpen, setIsAddOpen] = useState(false);
let [isAddServiceTokenDialogOpen, setIsAddServiceTokenDialogOpen] = let [isAddServiceTokenDialogOpen, setIsAddServiceTokenDialogOpen] =
@@ -101,18 +100,14 @@ export default function SettingsBasic() {
/> />
<div className="flex flex-row mr-6 max-w-5xl"> <div className="flex flex-row mr-6 max-w-5xl">
<div className="w-full max-h-screen pb-2 overflow-y-auto"> <div className="w-full max-h-screen pb-2 overflow-y-auto">
<NavHeader <NavHeader pageName="Project Settings" isProjectRelated={true} />
pageName="Project Settings"
isProjectRelated={true}
/>
<div className="flex flex-row justify-between items-center ml-6 my-8 text-xl max-w-5xl"> <div className="flex flex-row justify-between items-center ml-6 my-8 text-xl max-w-5xl">
<div className="flex flex-col justify-start items-start text-3xl"> <div className="flex flex-col justify-start items-start text-3xl">
<p className="font-semibold mr-4 text-gray-200"> <p className="font-semibold mr-4 text-gray-200">
Project Settings Project Settings
</p> </p>
<p className="font-normal mr-4 text-gray-400 text-base"> <p className="font-normal mr-4 text-gray-400 text-base">
These settings only apply to the currently These settings only apply to the currently selected Project.
selected Project.
</p> </p>
</div> </div>
</div> </div>
@@ -120,14 +115,10 @@ export default function SettingsBasic() {
<div className="flex flex-col"> <div className="flex flex-col">
<div className="min-w-md mt-2 flex flex-col items-start"> <div className="min-w-md mt-2 flex flex-col items-start">
<div className="bg-white/5 rounded-md px-6 pt-6 pb-4 flex flex-col items-start flex flex-col items-start w-full mb-6 pt-2"> <div className="bg-white/5 rounded-md px-6 pt-6 pb-4 flex flex-col items-start flex flex-col items-start w-full mb-6 pt-2">
<p className="text-xl font-semibold mb-4"> <p className="text-xl font-semibold mb-4">Display Name</p>
Display Name
</p>
<div className="max-h-28 w-full max-w-md mr-auto"> <div className="max-h-28 w-full max-w-md mr-auto">
<InputField <InputField
onChangeHandler={ onChangeHandler={modifyWorkspaceName}
modifyWorkspaceName
}
type="varName" type="varName"
value={workspaceName} value={workspaceName}
placeholder="" placeholder=""
@@ -135,14 +126,10 @@ export default function SettingsBasic() {
/> />
</div> </div>
<div className="flex justify-start w-full"> <div className="flex justify-start w-full">
<div <div className={`flex justify-start max-w-sm mt-4 mb-2`}>
className={`flex justify-start max-w-sm mt-4 mb-2`}
>
<Button <Button
text="Save Changes" text="Save Changes"
onButtonPressed={() => onButtonPressed={() => submitChanges(workspaceName)}
submitChanges(workspaceName)
}
color="mineshaft" color="mineshaft"
size="md" size="md"
active={buttonReady} active={buttonReady}
@@ -153,19 +140,15 @@ export default function SettingsBasic() {
</div> </div>
</div> </div>
<div className="bg-white/5 rounded-md px-6 pt-6 pb-2 flex flex-col items-start flex flex-col items-start w-full mb-6 mt-4"> <div className="bg-white/5 rounded-md px-6 pt-6 pb-2 flex flex-col items-start flex flex-col items-start w-full mb-6 mt-4">
<p className="text-xl font-semibold self-start"> <p className="text-xl font-semibold self-start">Project ID</p>
Project ID
</p>
<p className="text-base text-gray-400 font-normal self-start mt-4"> <p className="text-base text-gray-400 font-normal self-start mt-4">
To integrate Infisical into your code To integrate Infisical into your code base and get automatic
base and get automatic injection of injection of environmental variables, you should use the
environmental variables, you should use following Project ID.
the following Project ID.
</p> </p>
<p className="text-base text-gray-400 font-normal self-start"> <p className="text-base text-gray-400 font-normal self-start">
For more guidance, including code For more guidance, including code snipets for various
snipets for various languages and languages and frameworks, see{" "}
frameworks, see{" "}
{/* eslint-disable-next-line react/jsx-no-target-blank */} {/* eslint-disable-next-line react/jsx-no-target-blank */}
<a <a
href="https://infisical.com/docs/getting-started/introduction" href="https://infisical.com/docs/getting-started/introduction"
@@ -194,19 +177,15 @@ export default function SettingsBasic() {
Service Tokens Service Tokens
</p> </p>
<p className="text-base text-gray-400 mb-4"> <p className="text-base text-gray-400 mb-4">
Every service token is specific Every service token is specific to you, a certain
to you, a certain project and a project and a certain environment within this project.
certain environment within this
project.
</p> </p>
</div> </div>
<div className="w-48"> <div className="w-48">
<Button <Button
text="Add New Token" text="Add New Token"
onButtonPressed={() => { onButtonPressed={() => {
setIsAddServiceTokenDialogOpen( setIsAddServiceTokenDialogOpen(true);
true
);
}} }}
color="mineshaft" color="mineshaft"
icon={faPlus} icon={faPlus}
@@ -258,21 +237,16 @@ export default function SettingsBasic() {
</div> </div>
</div> </div>
<div className="bg-white/5 rounded-md px-6 pt-6 pb-6 border-l border-red pl-6 flex flex-col items-start flex flex-col items-start w-full mb-6 mt-4 pb-4 pt-2"> <div className="bg-white/5 rounded-md px-6 pt-6 pb-6 border-l border-red pl-6 flex flex-col items-start flex flex-col items-start w-full mb-6 mt-4 pb-4 pt-2">
<p className="text-xl font-bold text-red"> <p className="text-xl font-bold text-red">Danger Zone</p>
Danger Zone
</p>
<p className="mt-2 text-md text-gray-400"> <p className="mt-2 text-md text-gray-400">
As soon as you delete this project, you will not As soon as you delete this project, you will not be able to undo
be able to undo it. This will immediately remove it. This will immediately remove all the keys. If you still want
all the keys. If you still want to do that, to do that, please enter the name of the project below.
please enter the name of the project below.
</p> </p>
<div className="max-h-28 w-full max-w-md mr-auto mt-4"> <div className="max-h-28 w-full max-w-md mr-auto mt-4">
<InputField <InputField
label="Project to be Deleted" label="Project to be Deleted"
onChangeHandler={ onChangeHandler={setWorkspaceToBeDeletedName}
setWorkspaceToBeDeletedName
}
type="varName" type="varName"
value={workspaceToBeDeletedName} value={workspaceToBeDeletedName}
placeholder="" placeholder=""
@@ -287,8 +261,8 @@ export default function SettingsBasic() {
Delete Project Delete Project
</button> </button>
<p className="mt-0.5 ml-1 text-xs text-gray-500"> <p className="mt-0.5 ml-1 text-xs text-gray-500">
Note: You can only delete a project in case you Note: You can only delete a project in case you have more than
have more than one. one.
</p> </p>
</div> </div>
</div> </div>
+20 -52
View File
@@ -7,13 +7,13 @@ import { useRouter } from "next/router";
import { faCheck, faWarning, faX } from "@fortawesome/free-solid-svg-icons"; import { faCheck, faWarning, faX } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import Aes256Gcm from "~/components/utilities/cryptography/aes-256-gcm";
import Button from "~/components/basic/buttons/Button"; import Button from "~/components/basic/buttons/Button";
import Error from "~/components/basic/Error"; import Error from "~/components/basic/Error";
import InputField from "~/components/basic/InputField"; 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 attemptLogin from "~/utilities/attemptLogin";
import passwordCheck from "~/utilities/checks/PasswordCheck"; import passwordCheck from "~/utilities/checks/PasswordCheck";
import issueBackupKey from "~/components/utilities/cryptography/issueBackupKey";
import checkEmailVerificationCode from "./api/auth/CheckEmailVerificationCode"; import checkEmailVerificationCode from "./api/auth/CheckEmailVerificationCode";
import completeAccountInformationSignup from "./api/auth/CompleteAccountInformationSignup"; import completeAccountInformationSignup from "./api/auth/CompleteAccountInformationSignup";
@@ -184,9 +184,7 @@ export default function SignUp() {
password password
.slice(0, 32) .slice(0, 32)
.padStart( .padStart(
32 + 32 + (password.slice(0, 32).length - new Blob([password]).size),
(password.slice(0, 32).length -
new Blob([password]).size),
"0" "0"
) )
); );
@@ -199,8 +197,7 @@ export default function SignUp() {
}, },
async () => { async () => {
client.createVerifier(async (err, result) => { client.createVerifier(async (err, result) => {
const response = await completeAccountInformationSignup( const response = await completeAccountInformationSignup({
{
email, email,
firstName, firstName,
lastName, lastName,
@@ -212,18 +209,14 @@ export default function SignUp() {
salt: result.salt, salt: result.salt,
verifier: result.verifier, verifier: result.verifier,
token: verificationToken, token: verificationToken,
} });
);
// if everything works, go the main dashboard page. // if everything works, go the main dashboard page.
if (!errorCheck && response.status == "200") { if (!errorCheck && response.status == "200") {
response = await response.json(); response = await response.json();
localStorage.setItem("publicKey", PUBLIC_KEY); localStorage.setItem("publicKey", PUBLIC_KEY);
localStorage.setItem( localStorage.setItem("encryptedPrivateKey", ciphertext);
"encryptedPrivateKey",
ciphertext
);
localStorage.setItem("iv", iv); localStorage.setItem("iv", iv);
localStorage.setItem("tag", tag); localStorage.setItem("tag", tag);
@@ -282,15 +275,11 @@ export default function SignUp() {
</div> */} </div> */}
<div className="flex flex-col items-center justify-center w-5/6 md:w-full md:p-2 max-h-28 max-w-xs md:max-w-md mx-auto mt-4 md:mt-4 text-sm text-center md:text-left"> <div className="flex flex-col items-center justify-center w-5/6 md:w-full md:p-2 max-h-28 max-w-xs md:max-w-md mx-auto mt-4 md:mt-4 text-sm text-center md:text-left">
<p className="text-gray-400 mt-2 md:mx-0.5"> <p className="text-gray-400 mt-2 md:mx-0.5">
By creating an account, you agree to our Terms and have read By creating an account, you agree to our Terms and have read and
and acknowledged the Privacy Policy. acknowledged the Privacy Policy.
</p> </p>
<div className="text-l mt-6 m-2 md:m-8 px-8 py-1 text-lg"> <div className="text-l mt-6 m-2 md:m-8 px-8 py-1 text-lg">
<Button <Button text="Get Started" onButtonPressed={emailCheck} size="lg" />
text="Get Started"
onButtonPressed={emailCheck}
size="lg"
/>
</div> </div>
</div> </div>
</div> </div>
@@ -327,11 +316,7 @@ export default function SignUp() {
<Error text="Oops. Your code is wrong. Please try again." /> <Error text="Oops. Your code is wrong. Please try again." />
)} )}
<div className="flex max-w-min flex-col items-center justify-center md:p-2 max-h-24 max-w-md mx-auto text-lg px-4 mt-4 mb-2"> <div className="flex max-w-min flex-col items-center justify-center md:p-2 max-h-24 max-w-md mx-auto text-lg px-4 mt-4 mb-2">
<Button <Button text="Verify" onButtonPressed={incrementStep} size="lg" />
text="Verify"
onButtonPressed={incrementStep}
size="lg"
/>
</div> </div>
<div className="flex flex-col items-center justify-center w-full max-h-24 max-w-md mx-auto pt-2"> <div className="flex flex-col items-center justify-center w-full max-h-24 max-w-md mx-auto pt-2">
{/* <Link href="/login"> {/* <Link href="/login">
@@ -393,9 +378,7 @@ export default function SignUp() {
value={password} value={password}
isRequired isRequired
error={ error={
passwordErrorLength && passwordErrorLength && passwordErrorNumber && passwordErrorLowerCase
passwordErrorNumber &&
passwordErrorLowerCase
} }
/> />
{passwordErrorLength || {passwordErrorLength ||
@@ -419,9 +402,7 @@ export default function SignUp() {
)} )}
<div <div
className={`${ className={`${
passwordErrorLength passwordErrorLength ? "text-gray-400" : "text-gray-600"
? "text-gray-400"
: "text-gray-600"
} text-sm`} } text-sm`}
> >
14 characters 14 characters
@@ -441,9 +422,7 @@ export default function SignUp() {
)} )}
<div <div
className={`${ className={`${
passwordErrorLowerCase passwordErrorLowerCase ? "text-gray-400" : "text-gray-600"
? "text-gray-400"
: "text-gray-600"
} text-sm`} } text-sm`}
> >
1 lowercase character 1 lowercase character
@@ -463,9 +442,7 @@ export default function SignUp() {
)} )}
<div <div
className={`${ className={`${
passwordErrorNumber passwordErrorNumber ? "text-gray-400" : "text-gray-600"
? "text-gray-400"
: "text-gray-600"
} text-sm`} } text-sm`}
> >
1 number 1 number
@@ -495,20 +472,17 @@ export default function SignUp() {
</p> </p>
<div className="flex flex-col items-center justify-center w-full mt-4 md:mt-8 max-w-md text-gray-400 text-md rounded-md px-2"> <div className="flex flex-col items-center justify-center w-full mt-4 md:mt-8 max-w-md text-gray-400 text-md rounded-md px-2">
<div> <div>
If you get locked out of your account, your Emergency Kit is If you get locked out of your account, your Emergency Kit is the only
the only way to sign in. way to sign in.
</div> </div>
<div className="mt-3"> <div className="mt-3">
We recommend you download it and keep it somewhere safe. We recommend you download it and keep it somewhere safe.
</div> </div>
</div> </div>
<div className="w-full p-2 flex flex-row items-center bg-white/10 text-gray-400 rounded-md max-w-xs md:max-w-md mx-auto mt-4"> <div className="w-full p-2 flex flex-row items-center bg-white/10 text-gray-400 rounded-md max-w-xs md:max-w-md mx-auto mt-4">
<FontAwesomeIcon <FontAwesomeIcon icon={faWarning} className="ml-2 mr-4 text-4xl" />
icon={faWarning} It contains your Secret Key which we cannot access or recover for you if
className="ml-2 mr-4 text-4xl" you lose it.
/>
It contains your Secret Key which we cannot access or recover
for you if you lose it.
</div> </div>
<div className="flex flex-row items-center justify-center w-3/4 md:w-full md:p-2 max-h-28 max-w-max mx-auto mt-6 py-1 md:mt-4 text-lg text-center md:text-left"> <div className="flex flex-row items-center justify-center w-3/4 md:w-full md:p-2 max-h-28 max-w-max mx-auto mt-6 py-1 md:mt-4 text-lg text-center md:text-left">
<Button <Button
@@ -567,13 +541,7 @@ export default function SignUp() {
/> />
</div> </div>
</Link> </Link>
{step == 1 {step == 1 ? step1 : step == 2 ? step2 : step == 3 ? step3 : step4}
? step1
: step == 2
? step2
: step == 3
? step3
: step4}
</div> </div>
</div> </div>
); );
+15 -32
View File
@@ -3,15 +3,15 @@ import Head from "next/head";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { faCheck, faWarning,faX } from "@fortawesome/free-solid-svg-icons"; import { faCheck, faWarning, faX } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import Aes256Gcm from "~/components/utilities/cryptography/aes-256-gcm";
import Button from "~/components/basic/buttons/Button"; import Button from "~/components/basic/buttons/Button";
import InputField from "~/components/basic/InputField"; 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 attemptLogin from "~/utilities/attemptLogin";
import passwordCheck from "~/utilities/checks/PasswordCheck"; import passwordCheck from "~/utilities/checks/PasswordCheck";
import issueBackupKey from "~/components/utilities/cryptography/issueBackupKey";
import completeAccountInformationSignupInvite from "./api/auth/CompleteAccountInformationSignupInvite"; import completeAccountInformationSignupInvite from "./api/auth/CompleteAccountInformationSignupInvite";
import verifySignupInvite from "./api/auth/VerifySignupInvite"; import verifySignupInvite from "./api/auth/VerifySignupInvite";
@@ -79,9 +79,7 @@ export default function SignupInvite() {
password password
.slice(0, 32) .slice(0, 32)
.padStart( .padStart(
32 + 32 + (password.slice(0, 32).length - new Blob([password]).size),
(password.slice(0, 32).length -
new Blob([password]).size),
"0" "0"
) )
); );
@@ -94,8 +92,7 @@ export default function SignupInvite() {
}, },
async () => { async () => {
client.createVerifier(async (err, result) => { client.createVerifier(async (err, result) => {
const response = const response = await completeAccountInformationSignupInvite({
await completeAccountInformationSignupInvite({
email, email,
firstName, firstName,
lastName, lastName,
@@ -113,10 +110,7 @@ export default function SignupInvite() {
response = await response.json(); response = await response.json();
localStorage.setItem("publicKey", PUBLIC_KEY); localStorage.setItem("publicKey", PUBLIC_KEY);
localStorage.setItem( localStorage.setItem("encryptedPrivateKey", ciphertext);
"encryptedPrivateKey",
ciphertext
);
localStorage.setItem("iv", iv); localStorage.setItem("iv", iv);
localStorage.setItem("tag", tag); localStorage.setItem("tag", tag);
@@ -222,9 +216,7 @@ export default function SignupInvite() {
value={password} value={password}
isRequired isRequired
error={ error={
passwordErrorLength && passwordErrorLength && passwordErrorNumber && passwordErrorLowerCase
passwordErrorNumber &&
passwordErrorLowerCase
} }
/> />
{passwordErrorLength || {passwordErrorLength ||
@@ -248,9 +240,7 @@ export default function SignupInvite() {
)} )}
<div <div
className={`${ className={`${
passwordErrorLength passwordErrorLength ? "text-gray-400" : "text-gray-600"
? "text-gray-400"
: "text-gray-600"
} text-sm`} } text-sm`}
> >
14 characters 14 characters
@@ -270,9 +260,7 @@ export default function SignupInvite() {
)} )}
<div <div
className={`${ className={`${
passwordErrorLowerCase passwordErrorLowerCase ? "text-gray-400" : "text-gray-600"
? "text-gray-400"
: "text-gray-600"
} text-sm`} } text-sm`}
> >
1 lowercase character 1 lowercase character
@@ -292,9 +280,7 @@ export default function SignupInvite() {
)} )}
<div <div
className={`${ className={`${
passwordErrorNumber passwordErrorNumber ? "text-gray-400" : "text-gray-600"
? "text-gray-400"
: "text-gray-600"
} text-sm`} } text-sm`}
> >
1 number 1 number
@@ -326,20 +312,17 @@ export default function SignupInvite() {
</p> </p>
<div className="flex flex-col items-center justify-center w-full mt-4 md:mt-8 max-w-md text-gray-400 text-md rounded-md px-2"> <div className="flex flex-col items-center justify-center w-full mt-4 md:mt-8 max-w-md text-gray-400 text-md rounded-md px-2">
<div> <div>
If you get locked out of your account, your Emergency Kit is If you get locked out of your account, your Emergency Kit is the only
the only way to sign in. way to sign in.
</div> </div>
<div className="mt-3"> <div className="mt-3">
We recommend you download it and keep it somewhere safe. We recommend you download it and keep it somewhere safe.
</div> </div>
</div> </div>
<div className="w-full p-2 flex flex-row items-center bg-white/10 text-gray-400 rounded-md max-w-xs md:max-w-md mx-auto mt-4"> <div className="w-full p-2 flex flex-row items-center bg-white/10 text-gray-400 rounded-md max-w-xs md:max-w-md mx-auto mt-4">
<FontAwesomeIcon <FontAwesomeIcon icon={faWarning} className="ml-2 mr-4 text-4xl" />
icon={faWarning} It contains your Secret Key which we cannot access or recover for you if
className="ml-2 mr-4 text-4xl" you lose it.
/>
It contains your Secret Key which we cannot access or recover
for you if you lose it.
</div> </div>
<div className="flex flex-row items-center justify-center w-3/4 md:w-full md:p-2 max-h-28 max-w-xs md:max-w-md mx-auto mt-6 md:mt-8 py-1 text-lg text-center md:text-left"> <div className="flex flex-row items-center justify-center w-3/4 md:w-full md:p-2 max-h-28 max-w-xs md:max-w-md mx-auto mt-6 md:mt-8 py-1 text-lg text-center md:text-left">
<Button <Button
+3 -10
View File
@@ -99,8 +99,7 @@ export default function Users() {
key: guidGenerator(), key: guidGenerator(),
firstName: user.user?.firstName, firstName: user.user?.firstName,
lastName: user.user?.lastName, lastName: user.user?.lastName,
email: email: user.user?.email == null ? user.inviteEmail : user.user?.email,
user.user?.email == null ? user.inviteEmail : user.user?.email,
role: user?.role, role: user?.role,
status: user?.status, status: user?.status,
userId: user.user?._id, userId: user.user?._id,
@@ -117,10 +116,7 @@ export default function Users() {
?.filter((user) => user.status == "accepted") ?.filter((user) => user.status == "accepted")
.map((user) => user.user.email) .map((user) => user.user.email)
.filter( .filter(
(email) => (email) => !tempUserList?.map((user1) => user1.email).includes(email)
!tempUserList
?.map((user1) => user1.email)
.includes(email)
)[0] )[0]
); );
}, []); }, []);
@@ -147,10 +143,7 @@ export default function Users() {
?.filter((user) => user.status == "accepted") ?.filter((user) => user.status == "accepted")
.map((user) => user.user.email) .map((user) => user.user.email)
.filter( .filter(
(email) => (email) => !userList?.map((user1) => user1.email).includes(email)
!userList
?.map((user1) => user1.email)
.includes(email)
)} )}
workspaceId={workspaceId} workspaceId={workspaceId}
setEmail={setEmail} setEmail={setEmail}
+1 -1
View File
@@ -3,4 +3,4 @@ module.exports = {
tailwindcss: {}, tailwindcss: {},
autoprefixer: {}, autoprefixer: {},
}, },
} };
+72 -73
View File
@@ -1244,101 +1244,101 @@ module.exports = {
colors: { colors: {
// You can generate your own colors with this tool: https://javisperez.github.io/tailwindcolorshades/ // You can generate your own colors with this tool: https://javisperez.github.io/tailwindcolorshades/
primary: { primary: {
50: '#fcfdf7', 50: "#fcfdf7",
100: '#f8fcee', 100: "#f8fcee",
200: '#eef6d5', 200: "#eef6d5",
300: '#e3f1bc', 300: "#e3f1bc",
400: '#cfe78a', 400: "#cfe78a",
500: '#badc58', 500: "#badc58",
600: '#a7c64f', 600: "#a7c64f",
700: '#8ca542', 700: "#8ca542",
800: '#708435', 800: "#708435",
900: '#5b6c2b', 900: "#5b6c2b",
DEFAULT: "#badc58", DEFAULT: "#badc58",
}, },
grey: "#0d1117", grey: "#0d1117",
mineshaft: { mineshaft: {
50: '#f5f5f5', 50: "#f5f5f5",
100: '#ebebeb', 100: "#ebebeb",
200: '#ccccce', 200: "#ccccce",
300: '#adaeb0', 300: "#adaeb0",
400: '#707174', 400: "#707174",
500: '#323439', 500: "#323439",
600: '#2d2f33', 600: "#2d2f33",
700: '#26272b', 700: "#26272b",
800: '#1e1f22', 800: "#1e1f22",
900: '#19191c', 900: "#19191c",
DEFAULT: "#323439", DEFAULT: "#323439",
}, },
chicago: { chicago: {
50: '#f7f7f7', 50: "#f7f7f7",
100: '#efefef', 100: "#efefef",
200: '#d6d6d7', 200: "#d6d6d7",
300: '#bdbebf', 300: "#bdbebf",
400: '#8c8d8e', 400: "#8c8d8e",
500: '#5b5c5e', 500: "#5b5c5e",
600: '#525355', 600: "#525355",
700: '#444547', 700: "#444547",
800: '#373738', 800: "#373738",
900: '#2d2d2e', 900: "#2d2d2e",
DEFAULT: "#5b5c5e", DEFAULT: "#5b5c5e",
}, },
bunker: { bunker: {
50: '#f3f4f4', 50: "#f3f4f4",
100: '#e8e8e9', 100: "#e8e8e9",
200: '#c5c6c8', 200: "#c5c6c8",
300: '#a2a4a6', 300: "#a2a4a6",
400: '#5d5f64', 400: "#5d5f64",
500: '#171b21', 500: "#171b21",
600: '#15181e', 600: "#15181e",
700: '#111419', 700: "#111419",
800: '#0e1014', 800: "#0e1014",
900: '#0b0d10', 900: "#0b0d10",
DEFAULT: "#171B21", DEFAULT: "#171B21",
}, },
githubblack: "#020409", githubblack: "#020409",
blue2: "#130f40", blue2: "#130f40",
blue1: "#3498db", blue1: "#3498db",
yellow: { yellow: {
50: '#fefcf3', 50: "#fefcf3",
100: '#fef9e7', 100: "#fef9e7",
200: '#fcf0c3', 200: "#fcf0c3",
300: '#f9e79f', 300: "#f9e79f",
400: '#f5d657', 400: "#f5d657",
500: '#f1c40f', 500: "#f1c40f",
600: '#d9b00e', 600: "#d9b00e",
700: '#b5930b', 700: "#b5930b",
800: '#917609', 800: "#917609",
900: '#766007', 900: "#766007",
DEFAULT: "#f1c40f", DEFAULT: "#f1c40f",
}, },
red: { red: {
50: '#fef6f5', 50: "#fef6f5",
100: '#fdedec', 100: "#fdedec",
200: '#f9d2ce', 200: "#f9d2ce",
300: '#f5b7b1', 300: "#f5b7b1",
400: '#ee8277', 400: "#ee8277",
500: '#e74c3c', 500: "#e74c3c",
600: '#d04436', 600: "#d04436",
700: '#ad392d', 700: "#ad392d",
800: '#8b2e24', 800: "#8b2e24",
900: '#71251d', 900: "#71251d",
DEFAULT: "#e74c3c", DEFAULT: "#e74c3c",
}, },
orange: "#f39c12", orange: "#f39c12",
green: { green: {
50: '#f5fcf8', 50: "#f5fcf8",
100: '#eafaf1', 100: "#eafaf1",
200: '#cbf2dc', 200: "#cbf2dc",
300: '#abebc6', 300: "#abebc6",
400: '#6ddb9c', 400: "#6ddb9c",
500: '#2ecc71', 500: "#2ecc71",
600: '#29b866', 600: "#29b866",
700: '#239955', 700: "#239955",
800: '#1c7a44', 800: "#1c7a44",
900: '#176437', 900: "#176437",
DEFAULT: "#2ecc71", DEFAULT: "#2ecc71",
} },
}, },
}, },
keyframes: { keyframes: {
@@ -1425,8 +1425,7 @@ module.exports = {
spin: "spin 4000ms ease-in-out infinite", spin: "spin 4000ms ease-in-out infinite",
cursor: "cursor .6s linear infinite alternate", cursor: "cursor .6s linear infinite alternate",
type: "type 2.7s ease-out .8s infinite alternate both", type: "type 2.7s ease-out .8s infinite alternate both",
"type-reverse": "type-reverse": "type 1.8s ease-out 0s infinite alternate-reverse both",
"type 1.8s ease-out 0s infinite alternate-reverse both",
wiggle: "wiggle 200ms ease-in-out", wiggle: "wiggle 200ms ease-in-out",
ping: "ping 1000ms ease-in-out infinite", ping: "ping 1000ms ease-in-out infinite",
popup: "popup 300ms ease-in-out", popup: "popup 300ms ease-in-out",