This commit is contained in:
seunghyunOh
2022-12-11 15:07:53 +09:00
parent d503102f75
commit c4b4829694
27 changed files with 745 additions and 740 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
import SecurityClient from '~/utilities/SecurityClient.js';
import SecurityClient from '~/utilities/SecurityClient';
/**
* This function is used to check if the user is authenticated.
+13 -13
View File
@@ -1,29 +1,29 @@
import SecurityClient from "~/utilities/SecurityClient";
import SecurityClient from '~/utilities/SecurityClient';
/**
* This route logs the user out. Note: the user should authorized to do this.
* We first try to log out - if the authorization fails (response.status = 401), we refetch the new token, and then retry
*/
const logout = async () => {
return SecurityClient.fetchCall("/api/v1/auth/logout", {
method: "POST",
return SecurityClient.fetchCall('/api/v1/auth/logout', {
method: 'POST',
headers: {
"Content-Type": "application/json",
'Content-Type': 'application/json'
},
credentials: "include",
credentials: 'include'
}).then((res) => {
if (res?.status == 200) {
SecurityClient.setToken("");
SecurityClient.setToken('');
// Delete the cookie by not setting a value; Alternatively clear the local storage
localStorage.setItem("publicKey", "");
localStorage.setItem("encryptedPrivateKey", "");
localStorage.setItem("iv", "");
localStorage.setItem("tag", "");
localStorage.setItem("PRIVATE_KEY", "");
console.log("User logged out", res);
localStorage.setItem('publicKey', '');
localStorage.setItem('encryptedPrivateKey', '');
localStorage.setItem('iv', '');
localStorage.setItem('tag', '');
localStorage.setItem('PRIVATE_KEY', '');
console.log('User logged out', res);
return res;
} else {
console.log("Failed to log out");
console.log('Failed to log out');
}
});
};
+1 -1
View File
@@ -1,4 +1,4 @@
import SecurityClient from '~/utilities/SecurityClient.js';
import SecurityClient from '~/utilities/SecurityClient';
/**
* This function fetches the encrypted secrets from the .env file
+7 -7
View File
@@ -1,21 +1,21 @@
import SecurityClient from "~/utilities/SecurityClient";
import SecurityClient from '~/utilities/SecurityClient';
/**
* This route lets us get info about a certain org
* @param {string} orgId - the organization ID
* @returns
*/
const getOrganization = ({ orgId }: { orgId: string; }) => {
return SecurityClient.fetchCall("/api/v1/organization/" + orgId, {
method: "GET",
const getOrganization = ({ orgId }: { orgId: string }) => {
return SecurityClient.fetchCall('/api/v1/organization/' + orgId, {
method: 'GET',
headers: {
"Content-Type": "application/json",
},
'Content-Type': 'application/json'
}
}).then(async (res) => {
if (res?.status == 200) {
return (await res.json()).organization;
} else {
console.log("Failed to get org info");
console.log('Failed to get org info');
}
});
};
+8 -11
View File
@@ -1,4 +1,4 @@
import SecurityClient from "~/utilities/SecurityClient";
import SecurityClient from '~/utilities/SecurityClient';
/**
* This route lets us get all the users in an org.
@@ -6,20 +6,17 @@ import SecurityClient from "~/utilities/SecurityClient";
* @param {string} obj.orgId - organization Id
* @returns
*/
const getOrganizationUsers = ({ orgId }: { orgId: string; }) => {
return SecurityClient.fetchCall(
"/api/v1/organization/" + orgId + "/users",
{
method: "GET",
headers: {
"Content-Type": "application/json",
},
const getOrganizationUsers = ({ orgId }: { orgId: string }) => {
return SecurityClient.fetchCall('/api/v1/organization/' + orgId + '/users', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
).then(async (res) => {
}).then(async (res) => {
if (res?.status == 200) {
return (await res.json()).users;
} else {
console.log("Failed to get org users");
console.log('Failed to get org users');
}
});
};
+6 -6
View File
@@ -1,20 +1,20 @@
import SecurityClient from "~/utilities/SecurityClient";
import SecurityClient from '~/utilities/SecurityClient';
/**
* This route lets us get the all the orgs of a certain user.
* @returns
*/
const getOrganizations = () => {
return SecurityClient.fetchCall("/api/v1/organization", {
method: "GET",
return SecurityClient.fetchCall('/api/v1/organization', {
method: 'GET',
headers: {
"Content-Type": "application/json",
},
'Content-Type': 'application/json'
}
}).then(async (res) => {
if (res?.status == 200) {
return (await res.json()).organizations;
} else {
console.log("Failed to get orgs of a user");
console.log('Failed to get orgs of a user');
}
});
};
+6 -6
View File
@@ -1,19 +1,19 @@
import SecurityClient from "~/utilities/SecurityClient";
import SecurityClient from '~/utilities/SecurityClient';
/**
* This route gets the information about a specific user.
*/
const getUser = () => {
return SecurityClient.fetchCall("/api/v1/user", {
method: "GET",
return SecurityClient.fetchCall('/api/v1/user', {
method: 'GET',
headers: {
"Content-Type": "application/json",
},
'Content-Type': 'application/json'
}
}).then(async (res) => {
if (res?.status == 200) {
return (await res.json()).user;
} else {
console.log("Failed to get user info");
console.log('Failed to get user info');
}
});
};
@@ -1,4 +1,4 @@
import SecurityClient from "~/utilities/SecurityClient";
import SecurityClient from '~/utilities/SecurityClient';
/**
* This route creates a new workspace for a user within a certain organization.
@@ -6,21 +6,27 @@ import SecurityClient from "~/utilities/SecurityClient";
* @param {string} organizationId - org ID
* @returns
*/
const createWorkspace = ( { workspaceName, organizationId }: { workspaceName: string; organizationId: string; }) => {
return SecurityClient.fetchCall("/api/v1/workspace", {
method: "POST",
const createWorkspace = ({
workspaceName,
organizationId
}: {
workspaceName: string;
organizationId: string;
}) => {
return SecurityClient.fetchCall('/api/v1/workspace', {
method: 'POST',
headers: {
"Content-Type": "application/json",
'Content-Type': 'application/json'
},
body: JSON.stringify({
workspaceName: workspaceName,
organizationId: organizationId,
}),
organizationId: organizationId
})
}).then(async (res) => {
if (res?.status == 200) {
return (await res.json()).workspace;
} else {
console.log("Failed to create a project");
console.log('Failed to create a project');
}
});
};
@@ -1,24 +1,21 @@
import SecurityClient from "~/utilities/SecurityClient";
import SecurityClient from '~/utilities/SecurityClient';
/**
* Get the latest key pairs from a certain workspace
* @param {string} workspaceId
* @returns
*/
const getLatestFileKey = ({ workspaceId } : { workspaceId: string; }) => {
return SecurityClient.fetchCall(
"/api/v1/key/" + workspaceId + "/latest",
{
method: "GET",
headers: {
"Content-Type": "application/json",
},
const getLatestFileKey = ({ workspaceId }: { workspaceId: string }) => {
return SecurityClient.fetchCall('/api/v1/key/' + workspaceId + '/latest', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
).then(async (res) => {
}).then(async (res) => {
if (res?.status == 200) {
return await res.json();
} else {
console.log("Failed to get the latest key pairs for a certain project");
console.log('Failed to get the latest key pairs for a certain project');
}
});
};
+8 -11
View File
@@ -1,24 +1,21 @@
import SecurityClient from "~/utilities/SecurityClient";
import SecurityClient from '~/utilities/SecurityClient';
/**
* This route lets us get the information of a certain project.
* @param {*} projectId - project ID (we renamed workspaces to projects in the app)
* @returns
*/
const getProjectInfo = ({ projectId }: { projectId: string; }) => {
return SecurityClient.fetchCall(
"/api/v1/workspace/" + projectId,
{
method: "GET",
headers: {
"Content-Type": "application/json",
},
const getProjectInfo = ({ projectId }: { projectId: string }) => {
return SecurityClient.fetchCall('/api/v1/workspace/' + projectId, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
).then(async (res) => {
}).then(async (res) => {
if (res?.status == 200) {
return (await res.json()).workspace;
} else {
console.log("Failed to get project info");
console.log('Failed to get project info');
}
});
};
@@ -1,24 +1,24 @@
import SecurityClient from "~/utilities/SecurityClient";
import SecurityClient from '~/utilities/SecurityClient';
/**
* This route lets us get all the users in the workspace.
* @param {string} workspaceId - workspace ID
* @returns
*/
const getWorkspaceUsers = ({ workspaceId }: { workspaceId: string; }) => {
const getWorkspaceUsers = ({ workspaceId }: { workspaceId: string }) => {
return SecurityClient.fetchCall(
"/api/v1/workspace/" + workspaceId + "/users",
'/api/v1/workspace/' + workspaceId + '/users',
{
method: "GET",
method: 'GET',
headers: {
"Content-Type": "application/json",
},
'Content-Type': 'application/json'
}
}
).then(async (res) => {
if (res?.status == 200) {
return (await res.json()).users;
} else {
console.log("Failed to get Project Users");
console.log('Failed to get Project Users');
}
});
};
@@ -1,4 +1,4 @@
import SecurityClient from "~/utilities/SecurityClient";
import SecurityClient from '~/utilities/SecurityClient';
interface Workspace {
__v: number;
@@ -12,18 +12,18 @@ interface Workspace {
* @returns
*/
const getWorkspaces = () => {
return SecurityClient.fetchCall("/api/v1/workspace", {
method: "GET",
return SecurityClient.fetchCall('/api/v1/workspace', {
method: 'GET',
headers: {
"Content-Type": "application/json",
},
'Content-Type': 'application/json'
}
}).then(async (res) => {
if (res?.status == 200) {
const data = (await res.json()) as unknown as { workspaces: Workspace[] };
return data.workspaces;
}
throw new Error("Failed to get projects");
throw new Error('Failed to get projects');
});
};
+72 -72
View File
@@ -1,7 +1,7 @@
import React, { Fragment, useCallback, useEffect, useState } from "react";
import Head from "next/head";
import Image from "next/image";
import { useRouter } from "next/router";
import React, { Fragment, useCallback, useEffect, useState } from 'react';
import Head from 'next/head';
import Image from 'next/image';
import { useRouter } from 'next/router';
import {
faArrowDownAZ,
faArrowDownZA,
@@ -18,29 +18,29 @@ import {
faPerson,
faPlus,
faShuffle,
faX,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Menu, Transition } from "@headlessui/react";
faX
} from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Menu, Transition } from '@headlessui/react';
import Button from "~/components/basic/buttons/Button";
import ListBox from "~/components/basic/Listbox";
import BottonRightPopup from "~/components/basic/popups/BottomRightPopup";
import { useNotificationContext } from "~/components/context/Notifications/NotificationProvider";
import DashboardInputField from "~/components/dashboard/DashboardInputField";
import DropZone from "~/components/dashboard/DropZone";
import NavHeader from "~/components/navigation/NavHeader";
import getSecretsForProject from "~/components/utilities/secrets/getSecretsForProject";
import pushKeys from "~/components/utilities/secrets/pushKeys";
import pushKeysIntegration from "~/components/utilities/secrets/pushKeysIntegration";
import guidGenerator from "~/utilities/randomId";
import Button from '~/components/basic/buttons/Button';
import ListBox from '~/components/basic/Listbox';
import BottonRightPopup from '~/components/basic/popups/BottomRightPopup';
import { useNotificationContext } from '~/components/context/Notifications/NotificationProvider';
import DashboardInputField from '~/components/dashboard/DashboardInputField';
import DropZone from '~/components/dashboard/DropZone';
import NavHeader from '~/components/navigation/NavHeader';
import getSecretsForProject from '~/components/utilities/secrets/getSecretsForProject';
import pushKeys from '~/components/utilities/secrets/pushKeys';
import pushKeysIntegration from '~/components/utilities/secrets/pushKeysIntegration';
import guidGenerator from '~/utilities/randomId';
import { envMapping } from "../../public/data/frequentConstants";
import getWorkspaceIntegrations from "../api/integrations/getWorkspaceIntegrations";
import getUser from "../api/user/getUser";
import checkUserAction from "../api/userActions/checkUserAction";
import registerUserAction from "../api/userActions/registerUserAction";
import getWorkspaces from "../api/workspace/getWorkspaces";
import { envMapping } from '../../public/data/frequentConstants';
import getWorkspaceIntegrations from '../api/integrations/getWorkspaceIntegrations';
import getUser from '../api/user/getUser';
import checkUserAction from '../api/userActions/checkUserAction';
import registerUserAction from '../api/userActions/registerUserAction';
import getWorkspaces from '../api/workspace/getWorkspaces';
/**
* This component represent a single row for an environemnt variable on the dashboard
@@ -61,7 +61,7 @@ const KeyPair = ({
modifyValue,
modifyVisibility,
isBlurred,
duplicates,
duplicates
}) => {
const [randomStringLength, setRandomStringLength] = useState(32);
@@ -114,7 +114,7 @@ const KeyPair = ({
<div
onClick={() =>
modifyVisibility(
keyPair[4] == "personal" ? "shared" : "personal",
keyPair[4] == 'personal' ? 'shared' : 'personal',
keyPair[1]
)
}
@@ -122,10 +122,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
@@ -138,7 +138,7 @@ const KeyPair = ({
modifyValue(
[...Array(randomStringLength)]
.map(() => Math.floor(Math.random() * 16).toString(16))
.join(""),
.join(''),
keyPair[1]
);
}
@@ -147,7 +147,7 @@ const KeyPair = ({
>
<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>
@@ -210,21 +210,21 @@ export default function Dashboard() {
const [fileState, setFileState] = useState([]);
const [buttonReady, setButtonReady] = useState(false);
const router = useRouter();
const [workspaceId, setWorkspaceId] = useState("");
const [workspaceId, setWorkspaceId] = useState('');
const [blurred, setBlurred] = useState(true);
const [isKeyAvailable, setIsKeyAvailable] = useState(true);
const [env, setEnv] = useState(
router.asPath.split("?").length == 1
? "Development"
: Object.keys(envMapping).includes(router.asPath.split("?")[1])
? router.asPath.split("?")[1]
: "Development"
router.asPath.split('?').length == 1
? 'Development'
: Object.keys(envMapping).includes(router.asPath.split('?')[1])
? router.asPath.split('?')[1]
: 'Development'
);
const [isNew, setIsNew] = useState(false);
const [searchKeys, setSearchKeys] = useState("");
const [searchKeys, setSearchKeys] = useState('');
const [errorDragAndDrop, setErrorDragAndDrop] = useState(false);
const [projectIdCopied, setProjectIdCopied] = useState(false);
const [sortMethod, setSortMethod] = useState("alphabetical");
const [sortMethod, setSortMethod] = useState('alphabetical');
const [checkDocsPopUpVisible, setCheckDocsPopUpVisible] = useState(false);
const [hasUserEverPushed, setHasUserEverPushed] = useState(false);
@@ -248,16 +248,16 @@ export default function Dashboard() {
// prompt the user if they try and leave with unsaved changes
useEffect(() => {
const warningText =
"Do you want to save your results before leaving this page?";
'Do you want to save your results before leaving this page?';
const handleWindowClose = (e) => {
if (!buttonReady) return;
e.preventDefault();
return (e.returnValue = warningText);
};
window.addEventListener("beforeunload", handleWindowClose);
window.addEventListener('beforeunload', handleWindowClose);
// router.events.on('routeChangeStart', beforeRouteHandler);
return () => {
window.removeEventListener("beforeunload", handleWindowClose);
window.removeEventListener('beforeunload', handleWindowClose);
// router.events.off('routeChangeStart', beforeRouteHandler);
};
}, [buttonReady]);
@@ -267,7 +267,7 @@ export default function Dashboard() {
*/
const reorderRows = () => {
setSortMethod(
sortMethod == "alphabetical" ? "-alphabetical" : "alphabetical"
sortMethod == 'alphabetical' ? '-alphabetical' : 'alphabetical'
);
};
@@ -277,13 +277,13 @@ export default function Dashboard() {
let userWorkspaces = await getWorkspaces();
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]);
router.push('/dashboard/' + listWorkspaces[0]);
}
if (env != router.asPath.split("?")[1]) {
router.push(router.asPath.split("?")[0] + "?" + env);
if (env != router.asPath.split('?')[1]) {
router.push(router.asPath.split('?')[0] + '?' + env);
}
setBlurred(true);
setWorkspaceId(router.query.id);
@@ -293,7 +293,7 @@ export default function Dashboard() {
setFileState,
setIsKeyAvailable,
setData,
workspaceId: router.query.id,
workspaceId: router.query.id
});
const user = await getUser();
@@ -304,11 +304,11 @@ export default function Dashboard() {
);
let userAction = await checkUserAction({
action: "first_time_secrets_pushed",
action: 'first_time_secrets_pushed'
});
setHasUserEverPushed(userAction ? true : false);
} catch (error) {
console.log("Error", error);
console.log('Error', error);
setData([]);
}
})();
@@ -317,7 +317,7 @@ export default function Dashboard() {
const addRow = () => {
setIsNew(false);
setData([...data, [guidGenerator(), data.length, "", "", "shared"]]);
setData([...data, [guidGenerator(), data.length, '', '', 'shared']]);
};
const deleteRow = (id) => {
@@ -385,15 +385,15 @@ export default function Dashboard() {
if (nameErrors) {
return createNotification({
text: "Solve all name errors first!",
type: "error",
text: 'Solve all name errors first!',
type: 'error'
});
}
if (duplicatesExist) {
return createNotification({
text: "Your secrets weren't saved; please fix the conflicts first.",
type: "error",
type: 'error'
});
}
@@ -406,7 +406,7 @@ export default function Dashboard() {
* If there are any, update environment variables for those integrations
*/
let integrations = await getWorkspaceIntegrations({
workspaceId: router.query.id,
workspaceId: router.query.id
});
integrations.map(async (integration) => {
if (
@@ -419,7 +419,7 @@ export default function Dashboard() {
);
await pushKeysIntegration({
obj: objIntegration,
integrationId: integration._id,
integrationId: integration._id
});
}
});
@@ -427,7 +427,7 @@ export default function Dashboard() {
// If this user has never saved environment variables before, show them a prompt to read docs
if (!hasUserEverPushed) {
setCheckDocsPopUpVisible(true);
await registerUserAction({ action: "first_time_secrets_pushed" });
await registerUserAction({ action: 'first_time_secrets_pushed' });
}
};
@@ -442,12 +442,12 @@ 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");
let alink = document.createElement('a');
alink.href = fileDownloadUrl;
alink.download = envMapping[env] + ".env";
alink.download = envMapping[env] + '.env';
alink.click();
};
@@ -459,7 +459,7 @@ export default function Dashboard() {
* This function copies the project id to the clipboard
*/
function copyToClipboard() {
var copyText = document.getElementById("myInput");
var copyText = document.getElementById('myInput');
copyText.select();
copyText.setSelectionRange(0, 99999); // For mobile devices
@@ -502,7 +502,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"
@@ -557,7 +557,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"
@@ -571,7 +571,7 @@ export default function Dashboard() {
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)}
placeholder={"Search keys..."}
placeholder={'Search keys...'}
/>
</div>
<div className="ml-2 min-w-max flex flex-row items-start justify-start">
@@ -580,7 +580,7 @@ export default function Dashboard() {
color="mineshaft"
size="icon-md"
icon={
sortMethod == "alphabetical"
sortMethod == 'alphabetical'
? faArrowDownAZ
: faArrowDownZA
}
@@ -651,10 +651,10 @@ export default function Dashboard() {
keyPair[2]
.toLowerCase()
.includes(searchKeys.toLowerCase()) &&
keyPair[4] == "personal"
keyPair[4] == 'personal'
)
.sort((a, b) =>
sortMethod == "alphabetical"
sortMethod == 'alphabetical'
? a[2].localeCompare(b[2])
: b[2].localeCompare(a[2])
)
@@ -680,7 +680,7 @@ export default function Dashboard() {
</div>
<div
className={`bg-white/5 mt-1 mb-2 rounded-md p-1 pb-2 max-w-5xl ${
data?.length > 8 ? "h-3/4" : "h-min"
data?.length > 8 ? 'h-3/4' : 'h-min'
}`}
>
<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">
@@ -705,10 +705,10 @@ export default function Dashboard() {
keyPair[2]
.toLowerCase()
.includes(searchKeys.toLowerCase()) &&
keyPair[4] == "shared"
keyPair[4] == 'shared'
)
.sort((a, b) =>
sortMethod == "alphabetical"
sortMethod == 'alphabetical'
? a[2].localeCompare(b[2])
: b[2].localeCompare(a[2])
)
@@ -766,10 +766,10 @@ export default function Dashboard() {
/>
)}
{fileState.message ==
"Failed membership validation for workspace" && (
'Failed membership validation for workspace' && (
<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
+78 -65
View File
@@ -1,36 +1,36 @@
import React, { useEffect, useState } from "react";
import Head from "next/head";
import Image from "next/image";
import { useRouter } from "next/router";
import React, { useEffect, useState } from 'react';
import Head from 'next/head';
import Image from 'next/image';
import { useRouter } from 'next/router';
import {
faArrowRight,
faCheck,
faRotate,
faX,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
faX
} from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Button from "~/components/basic/buttons/Button";
import ListBox from "~/components/basic/Listbox";
import NavHeader from "~/components/navigation/NavHeader";
import getSecretsForProject from "~/components/utilities/secrets/getSecretsForProject";
import pushKeysIntegration from "~/components/utilities/secrets/pushKeysIntegration";
import guidGenerator from "~/utilities/randomId";
import Button from '~/components/basic/buttons/Button';
import ListBox from '~/components/basic/Listbox';
import NavHeader from '~/components/navigation/NavHeader';
import getSecretsForProject from '~/components/utilities/secrets/getSecretsForProject';
import pushKeysIntegration from '~/components/utilities/secrets/pushKeysIntegration';
import guidGenerator from '~/utilities/randomId';
import {
envMapping,
frameworks,
import {
envMapping,
frameworks,
reverseEnvMapping
} from "../../public/data/frequentConstants";
import deleteIntegration from "../api/integrations/DeleteIntegration";
import deleteIntegrationAuth from "../api/integrations/DeleteIntegrationAuth";
import getIntegrationApps from "../api/integrations/GetIntegrationApps";
import getIntegrations from "../api/integrations/GetIntegrations";
import getWorkspaceAuthorizations from "../api/integrations/getWorkspaceAuthorizations";
import getWorkspaceIntegrations from "../api/integrations/getWorkspaceIntegrations";
import startIntegration from "../api/integrations/StartIntegration";
} from '../../public/data/frequentConstants';
import deleteIntegration from '../api/integrations/DeleteIntegration';
import deleteIntegrationAuth from '../api/integrations/DeleteIntegrationAuth';
import getIntegrationApps from '../api/integrations/GetIntegrationApps';
import getIntegrations from '../api/integrations/GetIntegrations';
import getWorkspaceAuthorizations from '../api/integrations/getWorkspaceAuthorizations';
import getWorkspaceIntegrations from '../api/integrations/getWorkspaceIntegrations';
import startIntegration from '../api/integrations/StartIntegration';
const crypto = require("crypto");
const crypto = require('crypto');
const Integration = ({ projectIntegration }) => {
const [integrationEnvironment, setIntegrationEnvironment] = useState(
@@ -47,7 +47,7 @@ const Integration = ({ projectIntegration }) => {
useEffect(async () => {
const tempHerokuApps = await getIntegrationApps({
integrationAuthId: projectIntegration.integrationAuth,
integrationAuthId: projectIntegration.integrationAuth
});
const tempHerokuAppNames = tempHerokuApps.map((app) => app.name);
setApps(tempHerokuAppNames);
@@ -67,9 +67,9 @@ const Integration = ({ projectIntegration }) => {
<ListBox
data={
!projectIntegration.isActive && [
"Development",
"Staging",
"Production",
'Development',
'Staging',
'Production'
]
}
selected={integrationEnvironment}
@@ -116,7 +116,7 @@ const Integration = ({ projectIntegration }) => {
const result = await startIntegration({
integrationId: projectIntegration._id,
environment: envMapping[integrationEnvironment],
appName: integrationApp,
appName: integrationApp
});
if (result?.status == 200) {
let currentSecrets = await getSecretsForProject({
@@ -124,18 +124,18 @@ const Integration = ({ projectIntegration }) => {
setFileState,
setIsKeyAvailable,
setData,
workspaceId: router.query.id,
workspaceId: router.query.id
});
let obj = Object.assign(
{},
...currentSecrets.map((row) => ({
[row[2]]: row[3],
[row[2]]: row[3]
}))
);
await pushKeysIntegration({
obj,
integrationId: projectIntegration._id,
integrationId: projectIntegration._id
});
router.reload();
}
@@ -148,7 +148,7 @@ const Integration = ({ projectIntegration }) => {
<Button
onButtonPressed={async () => {
await deleteIntegration({
integrationId: projectIntegration._id,
integrationId: projectIntegration._id
});
router.reload();
}}
@@ -168,20 +168,20 @@ export default function Integrations() {
const [projectIntegrations, setProjectIntegrations] = useState();
const [authorizations, setAuthorizations] = useState();
const router = useRouter();
const [csrfToken, setCsrfToken] = useState("");
const [csrfToken, setCsrfToken] = useState('');
useEffect(async () => {
const tempCSRFToken = crypto.randomBytes(16).toString("hex");
const tempCSRFToken = crypto.randomBytes(16).toString('hex');
setCsrfToken(tempCSRFToken);
localStorage.setItem("latestCSRFToken", tempCSRFToken);
localStorage.setItem('latestCSRFToken', tempCSRFToken);
let projectAuthorizations = await getWorkspaceAuthorizations({
workspaceId: router.query.id,
workspaceId: router.query.id
});
setAuthorizations(projectAuthorizations);
const projectIntegrations = await getWorkspaceIntegrations({
workspaceId: router.query.id,
workspaceId: router.query.id
});
setProjectIntegrations(projectIntegrations);
@@ -189,7 +189,7 @@ export default function Integrations() {
const integrationsData = await getIntegrations();
setIntegrations(integrationsData);
} catch (error) {
console.log("Error", error);
console.log('Error', error);
}
}, []);
@@ -239,7 +239,9 @@ export default function Integrations() {
)}
<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">Platform & Cloud Integrations</p>
<p className="font-semibold mr-4">
Platform & Cloud Integrations
</p>
</div>
<p className="mr-4 text-base text-gray-400">
Click on the itegration you want to connect. This will let your
@@ -260,23 +262,23 @@ export default function Integrations() {
{Object.keys(integrations).map((integration) => (
<div
className={`relative ${
["Heroku"].includes(integrations[integration].name)
? ""
: "opacity-50"
['Heroku'].includes(integrations[integration].name)
? ''
: 'opacity-50'
}`}
key={integrations[integration].name}
>
<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)
? "hover:bg-white/10 duration-200 cursor-pointer"
: "cursor-default grayscale"
['Heroku'].includes(integrations[integration].name)
? 'hover:bg-white/10 duration-200 cursor-pointer'
: 'cursor-default grayscale'
}`}
>
<Image
@@ -285,12 +287,12 @@ export default function Integrations() {
width={70}
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-4 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>
) : (
@@ -299,7 +301,7 @@ 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()) && (
@@ -313,7 +315,7 @@ export default function Integrations() {
authorization.integration ==
integrations[integration].name.toLowerCase()
)
.map((authorization) => authorization._id)[0],
.map((authorization) => authorization._id)[0]
});
router.reload();
}}
@@ -334,7 +336,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
@@ -351,7 +353,8 @@ export default function Integrations() {
<p className="mr-4 text-base text-gray-400">
Click on a framework to get the setup instructions.
</p>
</div><div className="grid gap-4 grid-cols-7 grid-rows-2 mx-6 mt-4 max-w-5xl">
</div>
<div className="grid gap-4 grid-cols-7 grid-rows-2 mx-6 mt-4 max-w-5xl">
{frameworks.map((framework) => (
<div key={framework.name}>
<a
@@ -359,14 +362,24 @@ export default function Integrations() {
rel="noopener"
className={`relative flex flex-row items-center justify-center bg-bunker-500 hover:bg-gradient-to-tr hover:from-sky-400 hover:to-primary duration-200 h-32 rounded-md p-0.5 items-center cursor-pointer`}
>
<div className={`font-semibold bg-bunker-500 flex flex-col items-center justify-center h-full w-full rounded-md text-gray-300 group-hover:text-gray-200 duration-200 ${framework?.name?.split(" ").length > 1 ? "text-sm px-1" : "text-xl px-2"} text-center w-full max-w-xs`}>
{framework?.image && <Image
src={`/images/integrations/${framework.image}.png`}
height={framework?.name ? 60 : 90}
width={framework?.name ? 60 : 90}
alt="integration logo"
></Image>}
{framework?.name && framework?.image && <div className="h-2"></div>}
<div
className={`font-semibold bg-bunker-500 flex flex-col items-center justify-center h-full w-full rounded-md text-gray-300 group-hover:text-gray-200 duration-200 ${
framework?.name?.split(' ').length > 1
? 'text-sm px-1'
: 'text-xl px-2'
} text-center w-full max-w-xs`}
>
{framework?.image && (
<Image
src={`/images/integrations/${framework.image}.png`}
height={framework?.name ? 60 : 90}
width={framework?.name ? 60 : 90}
alt="integration logo"
></Image>
)}
{framework?.name && framework?.image && (
<div className="h-2"></div>
)}
{framework?.name && framework.name}
</div>
</a>
+46 -46
View File
@@ -1,62 +1,62 @@
import React, { useEffect, useState } from "react";
import Head from "next/head";
import { useRouter } from "next/router";
import React, { useEffect, useState } from 'react';
import Head from 'next/head';
import { useRouter } from 'next/router';
import {
faMagnifyingGlass,
faPlus,
faX,
} from "@fortawesome/free-solid-svg-icons";
import { faCheck } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
faX
} from '@fortawesome/free-solid-svg-icons';
import { faCheck } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Button from "~/components/basic/buttons/Button";
import AddIncidentContactDialog from "~/components/basic/dialog/AddIncidentContactDialog";
import AddUserDialog from "~/components/basic/dialog/AddUserDialog";
import InputField from "~/components/basic/InputField";
import UserTable from "~/components/basic/table/UserTable";
import NavHeader from "~/components/navigation/NavHeader";
import guidGenerator from "~/utilities/randomId";
import Button from '~/components/basic/buttons/Button';
import AddIncidentContactDialog from '~/components/basic/dialog/AddIncidentContactDialog';
import AddUserDialog from '~/components/basic/dialog/AddUserDialog';
import InputField from '~/components/basic/InputField';
import UserTable from '~/components/basic/table/UserTable';
import NavHeader from '~/components/navigation/NavHeader';
import guidGenerator from '~/utilities/randomId';
import addUserToOrg from "../../api/organization/addUserToOrg";
import deleteIncidentContact from "../../api/organization/deleteIncidentContact";
import getIncidentContacts from "../../api/organization/getIncidentContacts";
import getOrganization from "../../api/organization/GetOrg";
import getOrganizationSubscriptions from "../../api/organization/GetOrgSubscription";
import getOrganizationUsers from "../../api/organization/GetOrgUsers";
import renameOrg from "../../api/organization/renameOrg";
import getUser from "../../api/user/getUser";
import deleteWorkspace from "../../api/workspace/deleteWorkspace";
import getWorkspaces from "../../api/workspace/getWorkspaces";
import addUserToOrg from '../../api/organization/addUserToOrg';
import deleteIncidentContact from '../../api/organization/deleteIncidentContact';
import getIncidentContacts from '../../api/organization/getIncidentContacts';
import getOrganization from '../../api/organization/GetOrg';
import getOrganizationSubscriptions from '../../api/organization/GetOrgSubscription';
import getOrganizationUsers from '../../api/organization/GetOrgUsers';
import renameOrg from '../../api/organization/renameOrg';
import getUser from '../../api/user/getUser';
import deleteWorkspace from '../../api/workspace/deleteWorkspace';
import getWorkspaces from '../../api/workspace/getWorkspaces';
export default function SettingsOrg() {
const [buttonReady, setButtonReady] = useState(false);
const router = useRouter();
const [orgName, setOrgName] = useState("");
const [emailUser, setEmailUser] = useState("");
const [workspaceToBeDeletedName, setWorkspaceToBeDeletedName] = useState("");
const [searchUsers, setSearchUsers] = useState("");
const [workspaceId, setWorkspaceId] = useState("");
const [orgName, setOrgName] = useState('');
const [emailUser, setEmailUser] = useState('');
const [workspaceToBeDeletedName, setWorkspaceToBeDeletedName] = useState('');
const [searchUsers, setSearchUsers] = useState('');
const [workspaceId, setWorkspaceId] = useState('');
const [isAddIncidentContactOpen, setIsAddIncidentContactOpen] =
useState(false);
const [isAddUserOpen, setIsAddUserOpen] = useState(
router.asPath.split("?")[1] == "invite"
router.asPath.split('?')[1] == 'invite'
);
const [incidentContacts, setIncidentContacts] = useState([]);
const [searchIncidentContact, setSearchIncidentContact] = useState("");
const [searchIncidentContact, setSearchIncidentContact] = useState('');
const [userList, setUserList] = useState();
const [personalEmail, setPersonalEmail] = useState("");
const [personalEmail, setPersonalEmail] = useState('');
let workspaceIdTemp;
const [email, setEmail] = useState("");
const [currentPlan, setCurrentPlan] = useState("");
const [email, setEmail] = useState('');
const [currentPlan, setCurrentPlan] = useState('');
useEffect(async () => {
let org = await getOrganization({
orgId: localStorage.getItem("orgData.id"),
orgId: localStorage.getItem('orgData.id')
});
let orgData = org;
setOrgName(orgData.name);
let incidentContactsData = await getIncidentContacts(
localStorage.getItem("orgData.id")
localStorage.getItem('orgData.id')
);
setIncidentContacts(incidentContactsData?.map((contact) => contact.email));
@@ -66,7 +66,7 @@ export default function SettingsOrg() {
workspaceIdTemp = router.query.id;
let orgUsers = await getOrganizationUsers({
orgId: localStorage.getItem("orgData.id"),
orgId: localStorage.getItem('orgData.id')
});
setUserList(
orgUsers.map((user) => ({
@@ -78,11 +78,11 @@ export default function SettingsOrg() {
status: user?.status,
userId: user.user?._id,
membershipId: user._id,
publicKey: user.user?.publicKey,
publicKey: user.user?.publicKey
}))
);
const subscriptions = await getOrganizationSubscriptions({
orgId: localStorage.getItem("orgData.id"),
orgId: localStorage.getItem('orgData.id')
});
setCurrentPlan(subscriptions.data[0].plan.product);
}, []);
@@ -93,7 +93,7 @@ export default function SettingsOrg() {
};
const submitChanges = (newOrgName) => {
renameOrg(localStorage.getItem("orgData.id"), newOrgName);
renameOrg(localStorage.getItem('orgData.id'), newOrgName);
setButtonReady(false);
};
@@ -118,8 +118,8 @@ export default function SettingsOrg() {
}
async function submitAddUserModal(email) {
await addUserToOrg(email, localStorage.getItem("orgData.id"));
setEmail("");
await addUserToOrg(email, localStorage.getItem('orgData.id'));
setEmail('');
setIsAddUserOpen(false);
router.reload();
}
@@ -128,7 +128,7 @@ export default function SettingsOrg() {
setIncidentContacts(
incidentContacts.filter((contact) => contact != incidentContact)
);
deleteIncidentContact(localStorage.getItem("orgData.id"), incidentContact);
deleteIncidentContact(localStorage.getItem('orgData.id'), incidentContact);
};
/**
@@ -148,7 +148,7 @@ export default function SettingsOrg() {
) {
await deleteWorkspace(router.query.id);
let userWorkspaces = await getWorkspaces();
router.push("/dashboard/" + userWorkspaces[0]._id);
router.push('/dashboard/' + userWorkspaces[0]._id);
}
}
};
@@ -241,7 +241,7 @@ export default function SettingsOrg() {
className="pl-2 text-gray-400 rounded-r-md bg-white/5 w-full h-full outline-none"
value={searchUsers}
onChange={(e) => setSearchUsers(e.target.value)}
placeholder={"Search members..."}
placeholder={'Search members...'}
/>
</div>
<div className="mt-2 ml-2 min-w-max flex flex-row items-start justify-start">
@@ -302,7 +302,7 @@ export default function SettingsOrg() {
className="pl-2 text-gray-400 rounded-tr-md bg-white/5 w-full h-full outline-none"
value={searchIncidentContact}
onChange={(e) => setSearchIncidentContact(e.target.value)}
placeholder={"Search..."}
placeholder={'Search...'}
/>
</div>
{incidentContacts?.filter((email) =>
+82 -82
View File
@@ -1,72 +1,72 @@
import React, { useEffect, useRef, useState } from "react";
import ReactCodeInput from "react-code-input";
import dynamic from "next/dynamic";
import Head from "next/head";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import { faCheck, faWarning, faX } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import React, { useEffect, useRef, useState } from 'react';
import ReactCodeInput from 'react-code-input';
import dynamic from 'next/dynamic';
import Head from 'next/head';
import Image from 'next/image';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { faCheck, faWarning, faX } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Button from "~/components/basic/buttons/Button";
import Error from "~/components/basic/Error";
import InputField from "~/components/basic/InputField";
import Aes256Gcm from "~/components/utilities/cryptography/aes-256-gcm";
import issueBackupKey from "~/components/utilities/cryptography/issueBackupKey";
import attemptLogin from "~/utilities/attemptLogin";
import passwordCheck from "~/utilities/checks/PasswordCheck";
import Button from '~/components/basic/buttons/Button';
import Error from '~/components/basic/Error';
import InputField from '~/components/basic/InputField';
import Aes256Gcm from '~/components/utilities/cryptography/aes-256-gcm';
import issueBackupKey from '~/components/utilities/cryptography/issueBackupKey';
import attemptLogin from '~/utilities/attemptLogin';
import passwordCheck from '~/utilities/checks/PasswordCheck';
import checkEmailVerificationCode from "./api/auth/CheckEmailVerificationCode";
import completeAccountInformationSignup from "./api/auth/CompleteAccountInformationSignup";
import sendVerificationEmail from "./api/auth/SendVerificationEmail";
import getWorkspaces from "./api/workspace/getWorkspaces";
import checkEmailVerificationCode from './api/auth/CheckEmailVerificationCode';
import completeAccountInformationSignup from './api/auth/CompleteAccountInformationSignup';
import sendVerificationEmail from './api/auth/SendVerificationEmail';
import getWorkspaces from './api/workspace/getWorkspaces';
// const ReactCodeInput = dynamic(import("react-code-input"));
const nacl = require("tweetnacl");
const jsrp = require("jsrp");
nacl.util = require("tweetnacl-util");
const nacl = require('tweetnacl');
const jsrp = require('jsrp');
nacl.util = require('tweetnacl-util');
const client = new jsrp.client();
// The stye for the verification code input
const props = {
inputStyle: {
fontFamily: "monospace",
margin: "4px",
MozAppearance: "textfield",
width: "55px",
borderRadius: "5px",
fontSize: "24px",
height: "55px",
paddingLeft: "7",
backgroundColor: "#0d1117",
color: "white",
border: "1px solid gray",
textAlign: "center",
},
fontFamily: 'monospace',
margin: '4px',
MozAppearance: 'textfield',
width: '55px',
borderRadius: '5px',
fontSize: '24px',
height: '55px',
paddingLeft: '7',
backgroundColor: '#0d1117',
color: 'white',
border: '1px solid gray',
textAlign: 'center'
}
} as const;
const propsPhone = {
inputStyle: {
fontFamily: "monospace",
margin: "4px",
MozAppearance: "textfield",
width: "40px",
borderRadius: "5px",
fontSize: "24px",
height: "40px",
paddingLeft: "7",
backgroundColor: "#0d1117",
color: "white",
border: "1px solid gray",
textAlign: "center",
},
fontFamily: 'monospace',
margin: '4px',
MozAppearance: 'textfield',
width: '40px',
borderRadius: '5px',
fontSize: '24px',
height: '40px',
paddingLeft: '7',
backgroundColor: '#0d1117',
color: 'white',
border: '1px solid gray',
textAlign: 'center'
}
} as const;
export default function SignUp() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [code, setCode] = useState("");
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [code, setCode] = useState('');
const [codeError, setCodeError] = useState(false);
const [firstNameError, setFirstNameError] = useState(false);
const [lastNameError, setLastNameError] = useState(false);
@@ -77,22 +77,22 @@ export default function SignUp() {
const [passwordErrorSpecialChar, setPasswordErrorSpecialChar] =
useState(false);
const [emailError, setEmailError] = useState(false);
const [emailErrorMessage, setEmailErrorMessage] = useState("");
const [emailErrorMessage, setEmailErrorMessage] = useState('');
const [step, setStep] = useState(1);
const router = useRouter();
const [errorLogin, setErrorLogin] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [backupKeyError, setBackupKeyError] = useState(false);
const [verificationToken, setVerificationToken] = useState();
const [verificationToken, setVerificationToken] = useState('');
const [backupKeyIssued, setBackupKeyIssued] = useState(false);
useEffect(() => {
const tryAuth = async () => {
try {
const userWorkspaces = await getWorkspaces();
router.push("/dashboard/" + userWorkspaces[0]._id);
router.push('/dashboard/' + userWorkspaces[0]._id);
} catch (error) {
console.log("Error - Not logged in yet");
console.log('Error - Not logged in yet');
}
};
tryAuth();
@@ -109,8 +109,8 @@ export default function SignUp() {
setStep(2);
} else if (step == 2) {
// Checking if the code matches the email.
const response = await checkEmailVerificationCode(email, code);
if (response.status === 200 || code == "111222") {
const response = await checkEmailVerificationCode({ email, code });
if (response.status === 200 || code == '111222') {
setVerificationToken((await response.json()).token);
setStep(3);
} else {
@@ -128,15 +128,15 @@ export default function SignUp() {
let emailCheckBool = false;
if (!email) {
setEmailError(true);
setEmailErrorMessage("Please enter your email.");
setEmailErrorMessage('Please enter your email.');
emailCheckBool = true;
} else if (
!email.includes("@") ||
!email.includes(".") ||
!email.includes('@') ||
!email.includes('.') ||
!/[a-z]/.test(email)
) {
setEmailError(true);
setEmailErrorMessage("Please enter a valid email.");
setEmailErrorMessage('Please enter a valid email.');
emailCheckBool = true;
} else {
setEmailError(false);
@@ -170,7 +170,7 @@ export default function SignUp() {
setPasswordErrorLength,
setPasswordErrorNumber,
setPasswordErrorLowerCase,
currentErrorCheck: errorCheck,
currentErrorCheck: errorCheck
});
if (!errorCheck) {
@@ -187,16 +187,16 @@ export default function SignUp() {
.slice(0, 32)
.padStart(
32 + (password.slice(0, 32).length - new Blob([password]).size),
"0"
'0'
)
) as { ciphertext: string; iv: string; tag: string };
localStorage.setItem("PRIVATE_KEY", PRIVATE_KEY);
localStorage.setItem('PRIVATE_KEY', PRIVATE_KEY);
client.init(
{
username: email,
password: password,
password: password
},
async () => {
client.createVerifier(
@@ -212,17 +212,17 @@ export default function SignUp() {
tag,
salt: result.salt,
verifier: result.verifier,
token: verificationToken,
token: verificationToken
});
// if everything works, go the main dashboard page.
if (response.status === 200) {
// response = await response.json();
localStorage.setItem("publicKey", PUBLIC_KEY);
localStorage.setItem("encryptedPrivateKey", ciphertext);
localStorage.setItem("iv", iv);
localStorage.setItem("tag", tag);
localStorage.setItem('publicKey', PUBLIC_KEY);
localStorage.setItem('encryptedPrivateKey', ciphertext);
localStorage.setItem('iv', iv);
localStorage.setItem('tag', tag);
try {
await attemptLogin(
@@ -295,10 +295,10 @@ export default function SignUp() {
const step2 = (
<div className="bg-bunker w-max mx-auto h-7/12 pt-10 pb-4 px-8 rounded-xl drop-shadow-xl mb-64 md:mb-16">
<p className="text-l flex justify-center text-gray-400">
{"We've"} sent a verification email to{" "}
{"We've"} sent a verification email to{' '}
</p>
<p className="text-l flex justify-center font-semibold my-2 text-gray-400">
{email}{" "}
{email}{' '}
</p>
<div className="hidden md:block">
<ReactCodeInput
@@ -383,7 +383,7 @@ export default function SignUp() {
setPasswordErrorLength,
setPasswordErrorNumber,
setPasswordErrorLowerCase,
currentErrorCheck: false,
currentErrorCheck: false
});
}}
type="password"
@@ -416,7 +416,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
@@ -436,7 +436,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
@@ -456,7 +456,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
@@ -505,13 +505,13 @@ export default function SignUp() {
await issueBackupKey({
email,
password,
personalName: firstName + " " + lastName,
personalName: firstName + ' ' + lastName,
setBackupKeyError,
setBackupKeyIssued,
setBackupKeyIssued
});
const userWorkspaces = await getWorkspaces();
const userWorkspace = userWorkspaces[0]._id;
router.push("/home/" + userWorkspace);
router.push('/home/' + userWorkspace);
}}
size="lg"
/>
+34 -34
View File
@@ -1,39 +1,39 @@
import React, { useEffect, useState } from "react";
import Head from "next/head";
import Image from "next/image";
import { useRouter } from "next/router";
import { faMagnifyingGlass, faPlus } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import React, { useEffect, useState } from 'react';
import Head from 'next/head';
import Image from 'next/image';
import { useRouter } from 'next/router';
import { faMagnifyingGlass, faPlus } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Button from "~/components/basic/buttons/Button";
import AddProjectMemberDialog from "~/components/basic/dialog/AddProjectMemberDialog";
import UserTable from "~/components/basic/table/UserTable";
import NavHeader from "~/components/navigation/NavHeader";
import guidGenerator from "~/utilities/randomId";
import Button from '~/components/basic/buttons/Button';
import AddProjectMemberDialog from '~/components/basic/dialog/AddProjectMemberDialog';
import UserTable from '~/components/basic/table/UserTable';
import NavHeader from '~/components/navigation/NavHeader';
import guidGenerator from '~/utilities/randomId';
import getOrganizationUsers from "../api/organization/GetOrgUsers";
import getUser from "../api/user/getUser";
import getOrganizationUsers from '../api/organization/GetOrgUsers';
import getUser from '../api/user/getUser';
// import DeleteUserDialog from '~/components/basic/dialog/DeleteUserDialog';
import addUserToWorkspace from "../api/workspace/addUserToWorkspace";
import getWorkspaceUsers from "../api/workspace/getWorkspaceUsers";
import uploadKeys from "../api/workspace/uploadKeys";
import addUserToWorkspace from '../api/workspace/addUserToWorkspace';
import getWorkspaceUsers from '../api/workspace/getWorkspaceUsers';
import uploadKeys from '../api/workspace/uploadKeys';
// #TODO: Update all the workspaceIds
const crypto = require("crypto");
const crypto = require('crypto');
const {
decryptAssymmetric,
encryptAssymmetric,
} = require("../../components/utilities/cryptography/crypto");
const nacl = require("tweetnacl");
nacl.util = require("tweetnacl-util");
encryptAssymmetric
} = require('../../components/utilities/cryptography/crypto');
const nacl = require('tweetnacl');
nacl.util = require('tweetnacl-util');
export default function Users() {
let [isAddOpen, setIsAddOpen] = useState(false);
// let [isDeleteOpen, setIsDeleteOpen] = useState(false);
// let [userIdToBeDeleted, setUserIdToBeDeleted] = useState(false);
let [email, setEmail] = useState("");
const [personalEmail, setPersonalEmail] = useState("");
const [searchUsers, setSearchUsers] = useState("");
let [email, setEmail] = useState('');
const [personalEmail, setPersonalEmail] = useState('');
const [searchUsers, setSearchUsers] = useState('');
const router = useRouter();
let workspaceId;
@@ -57,25 +57,25 @@ export default function Users() {
async function submitAddModal() {
let result = await addUserToWorkspace(email, router.query.id);
if (result?.invitee && result?.latestKey) {
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY");
const PRIVATE_KEY = localStorage.getItem('PRIVATE_KEY');
// assymmetrically decrypt symmetric key with local private key
const key = decryptAssymmetric({
ciphertext: result.latestKey.encryptedKey,
nonce: result.latestKey.nonce,
publicKey: result.latestKey.sender.publicKey,
privateKey: PRIVATE_KEY,
privateKey: PRIVATE_KEY
});
const { ciphertext, nonce } = encryptAssymmetric({
plaintext: key,
publicKey: result.invitee.publicKey,
privateKey: PRIVATE_KEY,
privateKey: PRIVATE_KEY
});
uploadKeys(router.query.id, result.invitee._id, ciphertext, nonce);
}
setEmail("");
setEmail('');
setIsAddOpen(false);
router.reload();
}
@@ -93,7 +93,7 @@ export default function Users() {
workspaceId = router.query.id;
let workspaceUsers = await getWorkspaceUsers({
workspaceId,
workspaceId
});
const tempUserList = workspaceUsers.map((user) => ({
key: guidGenerator(),
@@ -104,16 +104,16 @@ export default function Users() {
status: user?.status,
userId: user.user?._id,
membershipId: user._id,
publicKey: user.user?.publicKey,
publicKey: user.user?.publicKey
}));
setUserList(tempUserList);
const orgUsers = await getOrganizationUsers({
orgId: localStorage.getItem("orgData.id"),
orgId: localStorage.getItem('orgData.id')
});
setOrgUserList(orgUsers);
setEmail(
orgUsers
?.filter((user) => user.status == "accepted")
?.filter((user) => user.status == 'accepted')
.map((user) => user.user.email)
.filter(
(email) => !tempUserList?.map((user1) => user1.email).includes(email)
@@ -140,7 +140,7 @@ export default function Users() {
submitModal={submitAddModal}
email={email}
data={orgUserList
?.filter((user) => user.status == "accepted")
?.filter((user) => user.status == 'accepted')
.map((user) => user.user.email)
.filter(
(email) => !userList?.map((user1) => user1.email).includes(email)
@@ -159,7 +159,7 @@ export default function Users() {
className="pl-2 text-gray-400 rounded-r-md bg-white/5 w-full h-full outline-none"
value={searchUsers}
onChange={(e) => setSearchUsers(e.target.value)}
placeholder={"Search members..."}
placeholder={'Search members...'}
/>
</div>
<div className="mt-2 ml-2 min-w-max flex flex-row items-start justify-start mr-4">