mirror of
https://github.com/Infisical/infisical.git
synced 2025-03-25 14:05:03 +00:00
Merge branch 'main' into I-36-use-pre-built-frontend-image
This commit is contained in:
22
README.md
22
README.md
@ -48,11 +48,11 @@
|
||||
|
||||
And more.
|
||||
|
||||
## Get started
|
||||
## 🚀 Get started
|
||||
|
||||
To quickly get started, visit our [get started guide](https://infisical.com/docs/getting-started/introduction).
|
||||
|
||||
## What's cool about this?
|
||||
## 🔥 What's cool about this?
|
||||
|
||||
Infisical makes secret management simple and end-to-end encrypted by default. We're on a mission to make it more accessible to all developers, <i>not just security teams</i>.
|
||||
|
||||
@ -62,20 +62,20 @@ If you care about efficiency and security, then Infisical is right for you.
|
||||
|
||||
We are currently working hard to make Infisical more extensive. Need any integrations or want a new feature? Feel free to [create an issue](https://github.com/Infisical/infisical/issues) or [contribute](https://infisical.com/docs/contributing/overview) directly to the repository.
|
||||
|
||||
## Contributing
|
||||
## 🌱 Contributing
|
||||
|
||||
Whether it's big or small, we love contributions ❤️ Check out our guide to see how to [get started](https://infisical.com/docs/contributing/overview).
|
||||
|
||||
Not sure where to get started? [Book a free, non-pressure pairing sessions with one of our teammates](mailto:tony@infisical.com?subject=Pairing%20session&body=I'd%20like%20to%20do%20a%20pairing%20session!)!
|
||||
|
||||
## Community & Support
|
||||
## 💚 Community & Support
|
||||
|
||||
- [Slack](https://join.slack.com/t/infisical-users/shared_invite/zt-1kdbk07ro-RtoyEt_9E~fyzGo_xQYP6g) (For live discussion with the community and the Infisical team)
|
||||
- [GitHub Discussions](https://github.com/Infisical/infisical/discussions) (For help with building and deeper conversations about features)
|
||||
- [GitHub Issues](https://github.com/Infisical/infisical-cli/issues) (For any bugs and errors you encounter using Infisical)
|
||||
- [Twitter](https://twitter.com/infisical) (Get news fast)
|
||||
|
||||
## Status
|
||||
## 🐥 Status
|
||||
|
||||
- [x] Public Alpha: Anyone can sign up over at [infisical.com](https://infisical.com) but go easy on us, there are kinks and we're just getting started.
|
||||
- [ ] Public Beta: Stable enough for most non-enterprise use-cases.
|
||||
@ -83,13 +83,13 @@ Not sure where to get started? [Book a free, non-pressure pairing sessions with
|
||||
|
||||
We're currently in Public Alpha.
|
||||
|
||||
## Stay Up-to-Date
|
||||
## 🚨 Stay Up-to-Date
|
||||
|
||||
Infisical officially launched as v.1.0 on November 21st, 2022. However, a lot of new features are coming very quickly. Watch **releases** of this repository to be notified about future updates:
|
||||
|
||||

|
||||
|
||||
## Integrations
|
||||
## 🔌 Integrations
|
||||
|
||||
We're currently setting the foundation and building [integrations](https://infisical.com/docs/integrations/overview) so secrets can be synced everywhere. Any help is welcome! :)
|
||||
|
||||
@ -261,15 +261,15 @@ We're currently setting the foundation and building [integrations](https://infis
|
||||
</table>
|
||||
|
||||
|
||||
## Open-source vs. paid
|
||||
## 🏘 Open-source vs. paid
|
||||
|
||||
This repo is entirely MIT licensed, with the exception of the `ee` directory which will contain premium enterprise features requiring a Infisical license in the future. We're currently focused on developing non-enterprise offerings first that should suit most use-cases.
|
||||
|
||||
## Security
|
||||
## 🛡 Security
|
||||
|
||||
Looking to report a security vulnerability? Please don't post about it in GitHub issue. Instead, refer to our [SECURITY.md](./SECURITY.md) file.
|
||||
|
||||
## Contributors 🦸
|
||||
## 🦸 Contributors
|
||||
|
||||
[//]: contributor-faces
|
||||
|
||||
@ -277,4 +277,4 @@ Looking to report a security vulnerability? Please don't post about it in GitHub
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
|
||||
<a href="https://github.com/dangtony98"><img src="https://avatars.githubusercontent.com/u/25857006?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/mv-turtle"><img src="https://avatars.githubusercontent.com/u/78047717?s=96&v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/maidul98"><img src="https://avatars.githubusercontent.com/u/9300960?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/gangjun06"><img src="https://avatars.githubusercontent.com/u/50910815?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/reginaldbondoc"><img src="https://avatars.githubusercontent.com/u/7693108?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/SH5H"><img src="https://avatars.githubusercontent.com/u/25437192?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/hanywang2"><img src="https://avatars.githubusercontent.com/u/44352119?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/tobias-mintlify"><img src="https://avatars.githubusercontent.com/u/110702161?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/0xflotus"><img src="https://avatars.githubusercontent.com/u/26602940?v=4" width="50" height="50" alt=""/></a>
|
||||
<a href="https://github.com/dangtony98"><img src="https://avatars.githubusercontent.com/u/25857006?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/mv-turtle"><img src="https://avatars.githubusercontent.com/u/78047717?s=96&v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/maidul98"><img src="https://avatars.githubusercontent.com/u/9300960?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/gangjun06"><img src="https://avatars.githubusercontent.com/u/50910815?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/reginaldbondoc"><img src="https://avatars.githubusercontent.com/u/7693108?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/SH5H"><img src="https://avatars.githubusercontent.com/u/25437192?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/asharonbaltazar"><img src="https://avatars.githubusercontent.com/u/58940073?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/hanywang2"><img src="https://avatars.githubusercontent.com/u/44352119?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/tobias-mintlify"><img src="https://avatars.githubusercontent.com/u/110702161?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/0xflotus"><img src="https://avatars.githubusercontent.com/u/26602940?v=4" width="50" height="50" alt=""/></a>
|
||||
|
38
frontend/components/context/Notifications/Notification.tsx
Normal file
38
frontend/components/context/Notifications/Notification.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import { faXmarkCircle } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import classnames from "classnames";
|
||||
|
||||
import { Notification as NotificationType } from "./NotificationProvider";
|
||||
|
||||
interface NotificationProps {
|
||||
notification: NotificationType;
|
||||
clearNotification: (text?: string) => void;
|
||||
}
|
||||
|
||||
const Notification = ({
|
||||
notification,
|
||||
clearNotification,
|
||||
}: NotificationProps) => {
|
||||
return (
|
||||
<div
|
||||
className={classnames(
|
||||
"w-full flex items-center justify-between px-4 py-3 rounded pointer-events-auto",
|
||||
{
|
||||
"bg-green-600": notification.type === "success",
|
||||
"bg-red-500": notification.type === "error",
|
||||
}
|
||||
)}
|
||||
role="alert"
|
||||
>
|
||||
<p className="text-white text-sm font-bold">{notification.text}</p>
|
||||
<button
|
||||
className="bg-white/5 rounded-lg p-3"
|
||||
onClick={() => clearNotification(notification.text)}
|
||||
>
|
||||
<FontAwesomeIcon className="text-white" icon={faXmarkCircle} />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Notification;
|
@ -0,0 +1,64 @@
|
||||
import { createContext, ReactNode, useContext, useState } from "react";
|
||||
|
||||
import Notifications from "./Notifications";
|
||||
|
||||
type NotificationType = "success" | "error";
|
||||
|
||||
export type Notification = {
|
||||
text: string;
|
||||
type: NotificationType;
|
||||
};
|
||||
|
||||
type NotificationContextState = {
|
||||
createNotification: ({ text, type }: Notification) => void;
|
||||
};
|
||||
|
||||
const NotificationContext = createContext<NotificationContextState>({
|
||||
createNotification: () => console.log("createNotification not set!"),
|
||||
});
|
||||
|
||||
export const useNotificationContext = () => useContext(NotificationContext);
|
||||
|
||||
interface NotificationProviderProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
const NotificationProvider = ({ children }: NotificationProviderProps) => {
|
||||
const [notifications, setNotifications] = useState<Notification[]>([]);
|
||||
|
||||
const clearNotification = (text?: string) => {
|
||||
if (text) {
|
||||
return setNotifications((state) =>
|
||||
state.filter((notif) => notif.text !== text)
|
||||
);
|
||||
}
|
||||
|
||||
return setNotifications([]);
|
||||
};
|
||||
|
||||
const createNotification = ({ text, type = "success" }: Notification) => {
|
||||
const doesNotifExist = notifications.some((notif) => notif.text === text);
|
||||
|
||||
if (doesNotifExist) {
|
||||
return;
|
||||
}
|
||||
|
||||
return setNotifications((state) => [...state, { text, type }]);
|
||||
};
|
||||
|
||||
return (
|
||||
<NotificationContext.Provider
|
||||
value={{
|
||||
createNotification,
|
||||
}}
|
||||
>
|
||||
<Notifications
|
||||
notifications={notifications}
|
||||
clearNotification={clearNotification}
|
||||
/>
|
||||
{children}
|
||||
</NotificationContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotificationProvider;
|
28
frontend/components/context/Notifications/Notifications.tsx
Normal file
28
frontend/components/context/Notifications/Notifications.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import Notification from "./Notification";
|
||||
import { Notification as NotificationType } from "./NotificationProvider";
|
||||
|
||||
interface NoticationsProps {
|
||||
notifications: NotificationType[];
|
||||
clearNotification: (text?: string) => void;
|
||||
}
|
||||
|
||||
const Notifications = ({
|
||||
notifications,
|
||||
clearNotification,
|
||||
}: NoticationsProps) => {
|
||||
return (
|
||||
<div className="hidden fixed z-50 top-1 w-full inset-x-0 pointer-events-none md:flex justify-center">
|
||||
<div className="flex flex-col gap-y-2 w-96">
|
||||
{notifications.map((notif) => (
|
||||
<Notification
|
||||
key={notif.text}
|
||||
notification={notif}
|
||||
clearNotification={clearNotification}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Notifications;
|
@ -5,6 +5,7 @@ import getOrganizations from "~/pages/api/organization/getOrgs";
|
||||
import getOrganizationUserProjects from "~/pages/api/organization/GetOrgUserProjects";
|
||||
|
||||
import pushKeys from "./secrets/pushKeys";
|
||||
import { saveTokenToLocalStorage } from "./saveTokenToLocalStorage";
|
||||
import SecurityClient from "./SecurityClient";
|
||||
import Telemetry from "./telemetry/Telemetry";
|
||||
|
||||
@ -41,66 +42,38 @@ const attemptLogin = async (
|
||||
async () => {
|
||||
const clientPublicKey = client.getPublicKey();
|
||||
|
||||
let serverPublicKey, salt;
|
||||
try {
|
||||
let res = await login1(email, clientPublicKey);
|
||||
res = await res.json();
|
||||
serverPublicKey = res.serverPublicKey;
|
||||
salt = res.salt;
|
||||
} catch (err) {
|
||||
setErrorLogin(true);
|
||||
console.log("Wrong password", err);
|
||||
}
|
||||
const { serverPublicKey, salt } = await login1(email, clientPublicKey);
|
||||
|
||||
let response;
|
||||
try {
|
||||
client.setSalt(salt);
|
||||
client.setServerPublicKey(serverPublicKey);
|
||||
const clientProof = client.getProof(); // called M1
|
||||
response = await login2(email, clientProof);
|
||||
} catch (err) {
|
||||
setErrorLogin(true);
|
||||
console.log("Password verification failed");
|
||||
}
|
||||
|
||||
// if everything works, go the main dashboard page.
|
||||
try {
|
||||
if (response.status == "200") {
|
||||
response = await response.json();
|
||||
SecurityClient.setToken(response["token"]);
|
||||
const publicKey = response["publicKey"];
|
||||
const encryptedPrivateKey = response["encryptedPrivateKey"];
|
||||
const iv = response["iv"];
|
||||
const tag = response["tag"];
|
||||
// if everything works, go the main dashboard page.
|
||||
const { token, publicKey, encryptedPrivateKey, iv, tag } =
|
||||
await login2(email, clientProof);
|
||||
SecurityClient.setToken(token);
|
||||
|
||||
const PRIVATE_KEY = Aes256Gcm.decrypt(
|
||||
encryptedPrivateKey,
|
||||
iv,
|
||||
tag,
|
||||
password
|
||||
.slice(0, 32)
|
||||
.padStart(
|
||||
32 +
|
||||
(password.slice(0, 32).length - new Blob([password]).size),
|
||||
"0"
|
||||
)
|
||||
);
|
||||
const privateKey = Aes256Gcm.decrypt(
|
||||
encryptedPrivateKey,
|
||||
iv,
|
||||
tag,
|
||||
password
|
||||
.slice(0, 32)
|
||||
.padStart(
|
||||
32 + (password.slice(0, 32).length - new Blob([password]).size),
|
||||
"0"
|
||||
)
|
||||
);
|
||||
|
||||
try {
|
||||
localStorage.setItem("publicKey", publicKey);
|
||||
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
|
||||
);
|
||||
}
|
||||
} else {
|
||||
setErrorLogin(true);
|
||||
}
|
||||
saveTokenToLocalStorage({
|
||||
token,
|
||||
publicKey,
|
||||
encryptedPrivateKey,
|
||||
iv,
|
||||
tag,
|
||||
privateKey,
|
||||
});
|
||||
|
||||
const userOrgs = await getOrganizations();
|
||||
const userOrgsData = userOrgs.map((org) => org._id);
|
||||
@ -150,7 +123,7 @@ const attemptLogin = async (
|
||||
STRIPE_SECRET_KEY: ["sk_test_7348oyho4hfq398HIUOH78", "shared"],
|
||||
},
|
||||
workspaceId: projectToLogin,
|
||||
env: "Development"
|
||||
env: "Development",
|
||||
});
|
||||
}
|
||||
if (email) {
|
||||
|
29
frontend/components/utilities/saveTokenToLocalStorage.ts
Normal file
29
frontend/components/utilities/saveTokenToLocalStorage.ts
Normal file
@ -0,0 +1,29 @@
|
||||
interface Props {
|
||||
publicKey: string;
|
||||
encryptedPrivateKey: string;
|
||||
iv: string;
|
||||
tag: string;
|
||||
privateTag: string;
|
||||
}
|
||||
|
||||
export const saveTokenToLocalStorage = ({
|
||||
publicKey,
|
||||
encryptedPrivateKey,
|
||||
iv,
|
||||
tag,
|
||||
privateTag,
|
||||
}: Props) => {
|
||||
try {
|
||||
localStorage.setItem("publicKey", publicKey);
|
||||
localStorage.setItem("encryptedPrivateKey", encryptedPrivateKey);
|
||||
localStorage.setItem("iv", iv);
|
||||
localStorage.setItem("tag", tag);
|
||||
localStorage.setItem("PRIVATE_KEY", privateTag);
|
||||
} catch (err) {
|
||||
if (err instanceof Error) {
|
||||
throw new Error(
|
||||
"Unable to send the tokens in local storage:" + err.message
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
107
frontend/package-lock.json
generated
107
frontend/package-lock.json
generated
@ -50,13 +50,13 @@
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.4",
|
||||
"@types/node": "18.11.9",
|
||||
"@types/react": "^18.0.26",
|
||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||
"@typescript-eslint/parser": "^5.45.0",
|
||||
"autoprefixer": "^10.4.7",
|
||||
"eslint": "^8.29.0",
|
||||
"eslint-config-next": "^13.0.5",
|
||||
"eslint-import-resolver-typescript": "^3.5.2",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-simple-import-sort": "^8.0.0",
|
||||
"postcss": "^8.4.14",
|
||||
"prettier": "2.7.1",
|
||||
@ -1143,9 +1143,9 @@
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "18.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.15.tgz",
|
||||
"integrity": "sha512-iz3BtLuIYH1uWdsv6wXYdhozhqj20oD4/Hk2DNXIn1kFsmp9x8d9QB6FnPhfkbhd2PgEONt9Q1x/ebkwjfFLow==",
|
||||
"version": "18.0.26",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz",
|
||||
"integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==",
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
@ -2901,27 +2901,6 @@
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-prettier": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
|
||||
"integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"prettier-linter-helpers": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": ">=7.28.0",
|
||||
"prettier": ">=2.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"eslint-config-prettier": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-react": {
|
||||
"version": "7.31.11",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.11.tgz",
|
||||
@ -3289,12 +3268,6 @@
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fast-diff": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
|
||||
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fast-glob": {
|
||||
"version": "3.2.11",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
|
||||
@ -5624,18 +5597,6 @@
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-linter-helpers": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
|
||||
"integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fast-diff": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
@ -7666,7 +7627,8 @@
|
||||
"@headlessui/react": {
|
||||
"version": "1.6.6",
|
||||
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.6.6.tgz",
|
||||
"integrity": "sha512-MFJtmj9Xh/hhBMhLccGbBoSk+sk61BlP6sJe4uQcVMtXZhCgGqd2GyIQzzmsdPdTEWGSF434CBi8mnhR6um46Q=="
|
||||
"integrity": "sha512-MFJtmj9Xh/hhBMhLccGbBoSk+sk61BlP6sJe4uQcVMtXZhCgGqd2GyIQzzmsdPdTEWGSF434CBi8mnhR6um46Q==",
|
||||
"requires": {}
|
||||
},
|
||||
"@humanwhocodes/config-array": {
|
||||
"version": "0.11.7",
|
||||
@ -8007,9 +7969,9 @@
|
||||
"optional": true
|
||||
},
|
||||
"@types/react": {
|
||||
"version": "18.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.15.tgz",
|
||||
"integrity": "sha512-iz3BtLuIYH1uWdsv6wXYdhozhqj20oD4/Hk2DNXIn1kFsmp9x8d9QB6FnPhfkbhd2PgEONt9Q1x/ebkwjfFLow==",
|
||||
"version": "18.0.26",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz",
|
||||
"integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==",
|
||||
"requires": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
@ -8247,7 +8209,8 @@
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
|
||||
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"acorn-node": {
|
||||
"version": "1.8.2",
|
||||
@ -8450,7 +8413,8 @@
|
||||
"axios-auth-refresh": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/axios-auth-refresh/-/axios-auth-refresh-3.3.3.tgz",
|
||||
"integrity": "sha512-2IbDhJ/h6ddNBBnnzn1VFK/qx17pE9aVqiafB8rx5LVHsJ1HtFpUGkbXY7PzTG+8P9HJWcyA3fNZl9BikSuilg=="
|
||||
"integrity": "sha512-2IbDhJ/h6ddNBBnnzn1VFK/qx17pE9aVqiafB8rx5LVHsJ1HtFpUGkbXY7PzTG+8P9HJWcyA3fNZl9BikSuilg==",
|
||||
"requires": {}
|
||||
},
|
||||
"axobject-query": {
|
||||
"version": "2.2.0",
|
||||
@ -9400,15 +9364,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"eslint-plugin-prettier": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
|
||||
"integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"prettier-linter-helpers": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"eslint-plugin-react": {
|
||||
"version": "7.31.11",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.11.tgz",
|
||||
@ -9464,13 +9419,15 @@
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
|
||||
"integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"eslint-plugin-simple-import-sort": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-8.0.0.tgz",
|
||||
"integrity": "sha512-bXgJQ+lqhtQBCuWY/FUWdB27j4+lqcvXv5rUARkzbeWLwea+S5eBZEQrhnO+WgX3ZoJHVj0cn943iyXwByHHQw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"eslint-scope": {
|
||||
"version": "7.1.1",
|
||||
@ -9583,12 +9540,6 @@
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-diff": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
|
||||
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-glob": {
|
||||
"version": "3.2.11",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
|
||||
@ -11161,15 +11112,6 @@
|
||||
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
|
||||
"dev": true
|
||||
},
|
||||
"prettier-linter-helpers": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
|
||||
"integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-diff": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
@ -11441,7 +11383,8 @@
|
||||
"react-table": {
|
||||
"version": "7.8.0",
|
||||
"resolved": "https://registry.npmjs.org/react-table/-/react-table-7.8.0.tgz",
|
||||
"integrity": "sha512-hNaz4ygkZO4bESeFfnfOft73iBUj8K5oKi1EcSHPAibEydfsX2MyU6Z8KCr3mv3C9Kqqh71U+DhZkFvibbnPbA=="
|
||||
"integrity": "sha512-hNaz4ygkZO4bESeFfnfOft73iBUj8K5oKi1EcSHPAibEydfsX2MyU6Z8KCr3mv3C9Kqqh71U+DhZkFvibbnPbA==",
|
||||
"requires": {}
|
||||
},
|
||||
"read-cache": {
|
||||
"version": "1.0.0",
|
||||
@ -11482,7 +11425,8 @@
|
||||
"redux-thunk": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz",
|
||||
"integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q=="
|
||||
"integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==",
|
||||
"requires": {}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.11",
|
||||
@ -11834,7 +11778,8 @@
|
||||
"styled-jsx": {
|
||||
"version": "5.0.7",
|
||||
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz",
|
||||
"integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA=="
|
||||
"integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==",
|
||||
"requires": {}
|
||||
},
|
||||
"stylis": {
|
||||
"version": "4.0.13",
|
||||
@ -12197,12 +12142,14 @@
|
||||
"use-memo-one": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz",
|
||||
"integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ=="
|
||||
"integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"use-sync-external-store": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
|
||||
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA=="
|
||||
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
|
||||
"requires": {}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
|
@ -53,6 +53,7 @@
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.4",
|
||||
"@types/node": "18.11.9",
|
||||
"@types/react": "^18.0.26",
|
||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||
"@typescript-eslint/parser": "^5.45.0",
|
||||
"autoprefixer": "^10.4.7",
|
||||
|
@ -2,7 +2,8 @@ import { useEffect } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { config } from "@fortawesome/fontawesome-svg-core";
|
||||
|
||||
import Layout from "~/components/basic/Layout";
|
||||
import Layout from "~/components/basic/layout";
|
||||
import NotificationProvider from "~/components/context/Notifications/NotificationProvider";
|
||||
import RouteGuard from "~/components/RouteGuard";
|
||||
import { publicPaths } from "~/const";
|
||||
import Telemetry from "~/utilities/telemetry/Telemetry";
|
||||
@ -42,9 +43,11 @@ const App = ({ Component, pageProps, ...appProps }) => {
|
||||
|
||||
return (
|
||||
<RouteGuard>
|
||||
<Layout>
|
||||
<Component {...pageProps} />
|
||||
</Layout>
|
||||
<NotificationProvider>
|
||||
<Layout>
|
||||
<Component {...pageProps} />
|
||||
</Layout>
|
||||
</NotificationProvider>
|
||||
</RouteGuard>
|
||||
);
|
||||
};
|
||||
|
@ -1,20 +0,0 @@
|
||||
/**
|
||||
* This is the first step of the login process (pake)
|
||||
* @param {*} email
|
||||
* @param {*} clientPublicKey
|
||||
* @returns
|
||||
*/
|
||||
const login1 = (email, clientPublicKey) => {
|
||||
return fetch("/api/v1/auth/login1", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: email,
|
||||
clientPublicKey,
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
export default login1;
|
32
frontend/pages/api/auth/Login1.ts
Normal file
32
frontend/pages/api/auth/Login1.ts
Normal file
@ -0,0 +1,32 @@
|
||||
interface Login1 {
|
||||
serverPublicKey: string;
|
||||
salt: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the first step of the login process (pake)
|
||||
* @param {*} email
|
||||
* @param {*} clientPublicKey
|
||||
* @returns
|
||||
*/
|
||||
const login1 = async (email: string, clientPublicKey: string) => {
|
||||
const response = await fetch("/api/v1/auth/login1", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: email,
|
||||
clientPublicKey,
|
||||
}),
|
||||
});
|
||||
// need precise error handling about the status code
|
||||
if (response?.status === 200) {
|
||||
const data = (await response.json()) as unknown as Login1;
|
||||
return data;
|
||||
}
|
||||
|
||||
throw new Error("Wrong password");
|
||||
};
|
||||
|
||||
export default login1;
|
@ -1,28 +0,0 @@
|
||||
/**
|
||||
* This is the second step of the login process
|
||||
* @param {*} email
|
||||
* @param {*} clientPublicKey
|
||||
* @returns
|
||||
*/
|
||||
const login2 = (email, clientProof) => {
|
||||
return fetch("/api/v1/auth/login2", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: email,
|
||||
clientProof,
|
||||
}),
|
||||
credentials: "include",
|
||||
}).then((res) => {
|
||||
if (res.status == 200) {
|
||||
console.log("User logged in", res);
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to log in");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default login2;
|
36
frontend/pages/api/auth/Login2.ts
Normal file
36
frontend/pages/api/auth/Login2.ts
Normal file
@ -0,0 +1,36 @@
|
||||
interface Login2Response {
|
||||
encryptedPrivateKey: string;
|
||||
iv: string;
|
||||
publicKey: string;
|
||||
tag: string;
|
||||
token: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the second step of the login process
|
||||
* @param {*} email
|
||||
* @param {*} clientPublicKey
|
||||
* @returns
|
||||
*/
|
||||
const login2 = async (email: string, clientProof: string) => {
|
||||
const response = await fetch("/api/v1/auth/login2", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: email,
|
||||
clientProof,
|
||||
}),
|
||||
credentials: "include",
|
||||
});
|
||||
// need precise error handling about the status code
|
||||
if (response.status == 200) {
|
||||
const data = (await response.json()) as unknown as Login2Response;
|
||||
return data;
|
||||
}
|
||||
|
||||
throw new Error("Password verification failed");
|
||||
};
|
||||
|
||||
export default login2;
|
@ -26,6 +26,7 @@ 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";
|
||||
@ -60,7 +61,7 @@ const KeyPair = ({
|
||||
modifyValue,
|
||||
modifyVisibility,
|
||||
isBlurred,
|
||||
duplicates
|
||||
duplicates,
|
||||
}) => {
|
||||
const [randomStringLength, setRandomStringLength] = useState(32);
|
||||
|
||||
@ -227,6 +228,8 @@ export default function Dashboard() {
|
||||
const [checkDocsPopUpVisible, setCheckDocsPopUpVisible] = useState(false);
|
||||
const [hasUserEverPushed, setHasUserEverPushed] = useState(false);
|
||||
|
||||
const { createNotification } = useNotificationContext();
|
||||
|
||||
// #TODO: fix save message for changing reroutes
|
||||
// const beforeRouteHandler = (url) => {
|
||||
// const warningText =
|
||||
@ -370,46 +373,61 @@ export default function Dashboard() {
|
||||
);
|
||||
|
||||
// Checking if any of the secret keys start with a number - if so, don't do anything
|
||||
const nameErrors = !Object.keys(obj).map(key => !isNaN(key.charAt(0))).every(v => v === false);
|
||||
const duplicatesExist = data?.map(item => item[2]).filter((item, index) => index !== data?.map(item => item[2]).indexOf(item)).length > 0;
|
||||
const nameErrors = !Object.keys(obj)
|
||||
.map((key) => !isNaN(key.charAt(0)))
|
||||
.every((v) => v === false);
|
||||
const duplicatesExist =
|
||||
data
|
||||
?.map((item) => item[2])
|
||||
.filter(
|
||||
(item, index) => index !== data?.map((item) => item[2]).indexOf(item)
|
||||
).length > 0;
|
||||
|
||||
if (nameErrors) {
|
||||
console.log("Solve all name errors first!");
|
||||
} else if (duplicatesExist) {
|
||||
console.log("Remove the duplicated entries first!");
|
||||
} else {
|
||||
// Once "Save changes is clicked", disable that button
|
||||
setButtonReady(false);
|
||||
pushKeys({obj, workspaceId: router.query.id, env});
|
||||
|
||||
/**
|
||||
* Check which integrations are active for this project and environment
|
||||
* If there are any, update environment variables for those integrations
|
||||
*/
|
||||
let integrations = await getWorkspaceIntegrations({
|
||||
workspaceId: router.query.id,
|
||||
});
|
||||
integrations.map(async (integration) => {
|
||||
if (
|
||||
envMapping[env] == integration.environment &&
|
||||
integration.isActive == true
|
||||
) {
|
||||
let objIntegration = Object.assign(
|
||||
{},
|
||||
...data.map((row) => ({ [row[2]]: row[3] }))
|
||||
);
|
||||
await pushKeysIntegration({
|
||||
obj: objIntegration,
|
||||
integrationId: integration._id,
|
||||
});
|
||||
}
|
||||
return createNotification({
|
||||
text: "Solve all name errors first!",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
|
||||
// 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" });
|
||||
if (duplicatesExist) {
|
||||
return createNotification({
|
||||
text: "Your secrets weren't saved; please fix the conflicts first.",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
|
||||
// Once "Save changed is clicked", disable that button
|
||||
setButtonReady(false);
|
||||
pushKeys({ obj, workspaceId: router.query.id, env });
|
||||
|
||||
/**
|
||||
* Check which integrations are active for this project and environment
|
||||
* If there are any, update environment variables for those integrations
|
||||
*/
|
||||
let integrations = await getWorkspaceIntegrations({
|
||||
workspaceId: router.query.id,
|
||||
});
|
||||
integrations.map(async (integration) => {
|
||||
if (
|
||||
envMapping[env] == integration.environment &&
|
||||
integration.isActive == true
|
||||
) {
|
||||
let objIntegration = Object.assign(
|
||||
{},
|
||||
...data.map((row) => ({ [row[2]]: row[3] }))
|
||||
);
|
||||
await pushKeysIntegration({
|
||||
obj: objIntegration,
|
||||
integrationId: integration._id,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 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" });
|
||||
}
|
||||
};
|
||||
|
||||
@ -649,7 +667,13 @@ export default function Dashboard() {
|
||||
modifyKey={listenChangeKey}
|
||||
modifyVisibility={listenChangeVisibility}
|
||||
isBlurred={blurred}
|
||||
duplicates={data?.map(item => item[2]).filter((item, index) => index !== data?.map(item => item[2]).indexOf(item))}
|
||||
duplicates={data
|
||||
?.map((item) => item[2])
|
||||
.filter(
|
||||
(item, index) =>
|
||||
index !==
|
||||
data?.map((item) => item[2]).indexOf(item)
|
||||
)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
@ -697,7 +721,13 @@ export default function Dashboard() {
|
||||
modifyKey={listenChangeKey}
|
||||
modifyVisibility={listenChangeVisibility}
|
||||
isBlurred={blurred}
|
||||
duplicates={data?.map(item => item[2]).filter((item, index) => index !== data?.map(item => item[2]).indexOf(item))}
|
||||
duplicates={data
|
||||
?.map((item) => item[2])
|
||||
.filter(
|
||||
(item, index) =>
|
||||
index !==
|
||||
data?.map((item) => item[2]).indexOf(item)
|
||||
)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user