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