mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 13:22:08 +00:00
Merge branch 'main' of github.com:LemmyMwaura/infisical into secrets-dash-jumping-bug-#51
This commit is contained in:
+19
-10
@@ -1,4 +1,13 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
interface Props {
|
||||
encryptedPrivateKey: string;
|
||||
iv: string;
|
||||
tag: string;
|
||||
salt: string;
|
||||
verifier: string;
|
||||
clientProof: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the second step of the change password process (pake)
|
||||
@@ -11,12 +20,12 @@ const changePassword2 = ({
|
||||
tag,
|
||||
salt,
|
||||
verifier,
|
||||
clientProof,
|
||||
}) => {
|
||||
return SecurityClient.fetchCall("/api/v1/password/change-password", {
|
||||
method: "POST",
|
||||
clientProof
|
||||
}: Props) => {
|
||||
return SecurityClient.fetchCall('/api/v1/password/change-password', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
clientProof: clientProof,
|
||||
@@ -24,13 +33,13 @@ const changePassword2 = ({
|
||||
iv: iv,
|
||||
tag: tag,
|
||||
salt: salt,
|
||||
verifier: verifier,
|
||||
}),
|
||||
verifier: verifier
|
||||
})
|
||||
}).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to change the password");
|
||||
console.log('Failed to change the password');
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient.js";
|
||||
|
||||
/**
|
||||
* This function is used to check if the user is authenticated.
|
||||
* To do that, we get their tokens from cookies, and verify if they are good.
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @returns
|
||||
*/
|
||||
const checkAuth = async (req, res) => {
|
||||
return SecurityClient.fetchCall("/api/v1/auth/checkAuth", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}).then((res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Not authorized");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default checkAuth;
|
||||
@@ -0,0 +1,22 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This function is used to check if the user is authenticated.
|
||||
* To do that, we get their tokens from cookies, and verify if they are good.
|
||||
*/
|
||||
const checkAuth = async () => {
|
||||
return SecurityClient.fetchCall('/api/v1/auth/checkAuth', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}).then((res) => {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log('Not authorized');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default checkAuth;
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* This route check the verification code from the email that user just recieved
|
||||
* @param {*} email
|
||||
* @param {*} code
|
||||
* @returns
|
||||
*/
|
||||
const checkEmailVerificationCode = (email, code) => {
|
||||
return fetch("/api/v1/signup/email/verify", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: email,
|
||||
code: code,
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
export default checkEmailVerificationCode;
|
||||
@@ -0,0 +1,26 @@
|
||||
interface Props {
|
||||
email: string;
|
||||
code: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This route check the verification code from the email that user just recieved
|
||||
* @param {object} obj
|
||||
* @param {string} obj.email
|
||||
* @param {string} obj.code
|
||||
* @returns
|
||||
*/
|
||||
const checkEmailVerificationCode = ({ email, code }: Props) => {
|
||||
return fetch('/api/v1/signup/email/verify', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: email,
|
||||
code: code
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
export default checkEmailVerificationCode;
|
||||
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* This function is called in the end of the signup process.
|
||||
* It sends all the necessary nformation to the server.
|
||||
* @param {*} email
|
||||
* @param {*} firstName
|
||||
* @param {*} lastName
|
||||
* @param {*} workspace
|
||||
* @param {*} publicKey
|
||||
* @param {*} ciphertext
|
||||
* @param {*} iv
|
||||
* @param {*} tag
|
||||
* @param {*} salt
|
||||
* @param {*} verifier
|
||||
* @returns
|
||||
*/
|
||||
const completeAccountInformationSignup = ({
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
organizationName,
|
||||
publicKey,
|
||||
ciphertext,
|
||||
iv,
|
||||
tag,
|
||||
salt,
|
||||
verifier,
|
||||
token,
|
||||
}) => {
|
||||
return fetch("/api/v1/signup/complete-account/signup", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: "Bearer " + token,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
publicKey,
|
||||
encryptedPrivateKey: ciphertext,
|
||||
organizationName,
|
||||
iv,
|
||||
tag,
|
||||
salt,
|
||||
verifier,
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
export default completeAccountInformationSignup;
|
||||
@@ -0,0 +1,66 @@
|
||||
interface Props {
|
||||
email: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
publicKey: string;
|
||||
ciphertext: string;
|
||||
organizationName: string;
|
||||
iv: string;
|
||||
tag: string;
|
||||
salt: string;
|
||||
verifier: string;
|
||||
token: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called in the end of the signup process.
|
||||
* It sends all the necessary nformation to the server.
|
||||
* @param {object} obj
|
||||
* @param {string} obj.email - email of the user completing signup
|
||||
* @param {string} obj.firstName - first name of the user completing signup
|
||||
* @param {string} obj.lastName - last name of the user completing sign up
|
||||
* @param {string} obj.organizationName - organization name for this user (usually, [FIRST_NAME]'s organization)
|
||||
* @param {string} obj.publicKey - public key of the user completing signup
|
||||
* @param {string} obj.ciphertext
|
||||
* @param {string} obj.iv
|
||||
* @param {string} obj.tag
|
||||
* @param {string} obj.salt
|
||||
* @param {string} obj.verifier
|
||||
* @param {string} obj.token - token that confirms a user's identity
|
||||
* @returns
|
||||
*/
|
||||
const completeAccountInformationSignup = ({
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
organizationName,
|
||||
publicKey,
|
||||
ciphertext,
|
||||
iv,
|
||||
tag,
|
||||
salt,
|
||||
verifier,
|
||||
token
|
||||
}: Props) => {
|
||||
return fetch('/api/v1/signup/complete-account/signup', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + token
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
publicKey,
|
||||
encryptedPrivateKey: ciphertext,
|
||||
organizationName,
|
||||
iv,
|
||||
tag,
|
||||
salt,
|
||||
verifier
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
export default completeAccountInformationSignup;
|
||||
@@ -1,47 +0,0 @@
|
||||
/**
|
||||
* This function is called in the end of the signup process.
|
||||
* It sends all the necessary nformation to the server.
|
||||
* @param {*} email
|
||||
* @param {*} firstName
|
||||
* @param {*} lastName
|
||||
* @param {*} publicKey
|
||||
* @param {*} ciphertext
|
||||
* @param {*} iv
|
||||
* @param {*} tag
|
||||
* @param {*} salt
|
||||
* @param {*} verifier
|
||||
* @returns
|
||||
*/
|
||||
const completeAccountInformationSignupInvite = ({
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
publicKey,
|
||||
ciphertext,
|
||||
iv,
|
||||
tag,
|
||||
salt,
|
||||
verifier,
|
||||
token,
|
||||
}) => {
|
||||
return fetch("/api/v1/signup/complete-account/invite", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: "Bearer " + token,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: email,
|
||||
firstName: firstName,
|
||||
lastName: lastName,
|
||||
publicKey: publicKey,
|
||||
encryptedPrivateKey: ciphertext,
|
||||
iv: iv,
|
||||
tag: tag,
|
||||
salt: salt,
|
||||
verifier: verifier,
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
export default completeAccountInformationSignupInvite;
|
||||
@@ -0,0 +1,62 @@
|
||||
interface Props {
|
||||
email: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
publicKey: string;
|
||||
ciphertext: string;
|
||||
iv: string;
|
||||
tag: string;
|
||||
salt: string;
|
||||
verifier: string;
|
||||
token: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called in the end of the signup process.
|
||||
* It sends all the necessary nformation to the server.
|
||||
* @param {object} obj
|
||||
* @param {string} obj.email - email of the user completing signupinvite flow
|
||||
* @param {string} obj.firstName - first name of the user completing signupinvite flow
|
||||
* @param {string} obj.lastName - last name of the user completing signupinvite flow
|
||||
* @param {string} obj.publicKey - public key of the user completing signupinvite flow
|
||||
* @param {string} obj.ciphertext
|
||||
* @param {string} obj.iv
|
||||
* @param {string} obj.tag
|
||||
* @param {string} obj.salt
|
||||
* @param {string} obj.verifier
|
||||
* @param {string} obj.token - token that confirms a user's identity
|
||||
* @returns
|
||||
*/
|
||||
const completeAccountInformationSignupInvite = ({
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
publicKey,
|
||||
ciphertext,
|
||||
iv,
|
||||
tag,
|
||||
salt,
|
||||
verifier,
|
||||
token
|
||||
}: Props) => {
|
||||
return fetch('/api/v1/signup/complete-account/invite', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + token
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: email,
|
||||
firstName: firstName,
|
||||
lastName: lastName,
|
||||
publicKey: publicKey,
|
||||
encryptedPrivateKey: ciphertext,
|
||||
iv: iv,
|
||||
tag: tag,
|
||||
salt: salt,
|
||||
verifier: verifier
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
export default completeAccountInformationSignupInvite;
|
||||
@@ -1,40 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This is the route that issues a backup private key that will afterwards be added into a pdf
|
||||
*/
|
||||
const issueBackupPrivateKey = ({
|
||||
encryptedPrivateKey,
|
||||
iv,
|
||||
tag,
|
||||
salt,
|
||||
verifier,
|
||||
clientProof,
|
||||
}) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/password/backup-private-key",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
clientProof: clientProof,
|
||||
encryptedPrivateKey: encryptedPrivateKey,
|
||||
iv: iv,
|
||||
tag: tag,
|
||||
salt: salt,
|
||||
verifier: verifier,
|
||||
}),
|
||||
}
|
||||
).then((res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to issue the backup key");
|
||||
return res;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default issueBackupPrivateKey;
|
||||
@@ -0,0 +1,52 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
interface Props {
|
||||
encryptedPrivateKey: string;
|
||||
iv: string;
|
||||
tag: string;
|
||||
salt: string;
|
||||
verifier: string;
|
||||
clientProof: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the route that issues a backup private key that will afterwards be added into a pdf
|
||||
* @param {object} obj
|
||||
* @param {string} obj.encryptedPrivateKey
|
||||
* @param {string} obj.iv
|
||||
* @param {string} obj.tag
|
||||
* @param {string} obj.salt
|
||||
* @param {string} obj.verifier
|
||||
* @param {string} obj.clientProof
|
||||
* @returns
|
||||
*/
|
||||
const issueBackupPrivateKey = ({
|
||||
encryptedPrivateKey,
|
||||
iv,
|
||||
tag,
|
||||
salt,
|
||||
verifier,
|
||||
clientProof
|
||||
}: Props) => {
|
||||
return SecurityClient.fetchCall('/api/v1/password/backup-private-key', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
clientProof: clientProof,
|
||||
encryptedPrivateKey: encryptedPrivateKey,
|
||||
iv: iv,
|
||||
tag: tag,
|
||||
salt: salt,
|
||||
verifier: verifier
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res?.status !== 200) {
|
||||
console.log('Failed to issue the backup key');
|
||||
}
|
||||
return res;
|
||||
});
|
||||
};
|
||||
|
||||
export default issueBackupPrivateKey;
|
||||
@@ -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,26 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This is the first step of the change password process (pake)
|
||||
* @param {*} clientPublicKey
|
||||
* @returns
|
||||
*/
|
||||
const SRP1 = ({ clientPublicKey }) => {
|
||||
return SecurityClient.fetchCall("/api/v1/password/srp1", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
clientPublicKey,
|
||||
}),
|
||||
}).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return await res.json();
|
||||
} else {
|
||||
console.log("Failed to do the first step of SRP");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default SRP1;
|
||||
@@ -0,0 +1,30 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
interface Props {
|
||||
clientPublicKey: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the first step of the change password process (pake)
|
||||
* @param {string} clientPublicKey
|
||||
* @returns
|
||||
*/
|
||||
const SRP1 = ({ clientPublicKey }: Props) => {
|
||||
return SecurityClient.fetchCall('/api/v1/password/srp1', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
clientPublicKey
|
||||
})
|
||||
}).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return await res.json();
|
||||
} else {
|
||||
console.log('Failed to do the first step of SRP');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default SRP1;
|
||||
+6
-6
@@ -2,15 +2,15 @@
|
||||
* This route send the verification email to the user's email (contains a 6-digit verification code)
|
||||
* @param {*} email
|
||||
*/
|
||||
const sendVerificationEmail = (email) => {
|
||||
fetch("/api/v1/signup/email/signup", {
|
||||
method: "POST",
|
||||
const sendVerificationEmail = (email: string) => {
|
||||
fetch('/api/v1/signup/email/signup', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: email,
|
||||
}),
|
||||
email: email
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
const token = async (req, res) => {
|
||||
return fetch("/api/v1/auth/token", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
}).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return (await res.json()).token;
|
||||
} else {
|
||||
console.log("Getting a new token failed");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default token;
|
||||
@@ -0,0 +1,17 @@
|
||||
const token = async () => {
|
||||
return fetch('/api/v1/auth/token', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'include'
|
||||
}).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return (await res.json()).token;
|
||||
} else {
|
||||
console.log('Getting a new token failed');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default token;
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* This route verifies the signup invite link
|
||||
* @param {*} email
|
||||
* @param {*} code
|
||||
* @returns
|
||||
*/
|
||||
const verifySignupInvite = ({ email, code }) => {
|
||||
return fetch("/api/v1/invite-org/verify", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
code,
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
export default verifySignupInvite;
|
||||
@@ -0,0 +1,26 @@
|
||||
interface Props {
|
||||
email: string;
|
||||
code: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This route verifies the signup invite link
|
||||
* @param {object} obj
|
||||
* @param {string} obj.email - email that a user is trying to verify
|
||||
* @param {string} obj.code - code that a user received to the abovementioned email
|
||||
* @returns
|
||||
*/
|
||||
const verifySignupInvite = ({ email, code }: Props) => {
|
||||
return fetch('/api/v1/invite-org/verify', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
code
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
export default verifySignupInvite;
|
||||
@@ -1,16 +0,0 @@
|
||||
/**
|
||||
* This route lets us get the public key of infisical. Th euser doesn't have to be authenticated since this is just the public key.
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @returns
|
||||
*/
|
||||
const publicKeyInfisical = (req, res) => {
|
||||
return fetch("/api/v1/key/publicKey/infisical", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export default publicKeyInfisical;
|
||||
@@ -0,0 +1,10 @@
|
||||
const publicKeyInfisical = () => {
|
||||
return fetch('/api/v1/key/publicKey/infisical', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default publicKeyInfisical;
|
||||
@@ -1,33 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient.js";
|
||||
|
||||
/**
|
||||
* This function fetches the encrypted secrets from the .env file
|
||||
* @param {*} workspaceId
|
||||
* @param {*} env
|
||||
* @returns
|
||||
*/
|
||||
const getSecrets = async (workspaceId, env) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/secret/" +
|
||||
workspaceId +
|
||||
"?" +
|
||||
new URLSearchParams({
|
||||
environment: env,
|
||||
channel: "web",
|
||||
}),
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return await res.json();
|
||||
} else {
|
||||
console.log("Failed to get project secrets");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getSecrets;
|
||||
@@ -0,0 +1,33 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This function fetches the encrypted secrets from the .env file
|
||||
* @param {string} workspaceId - project is for which a user is trying to get secrets
|
||||
* @param {string} env - environment of a project for which a user is trying ot get secrets
|
||||
* @returns
|
||||
*/
|
||||
const getSecrets = async (workspaceId: string, env: string) => {
|
||||
return SecurityClient.fetchCall(
|
||||
'/api/v1/secret/' +
|
||||
workspaceId +
|
||||
'?' +
|
||||
new URLSearchParams({
|
||||
environment: env,
|
||||
channel: 'web'
|
||||
}),
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return await res.json();
|
||||
} else {
|
||||
console.log('Failed to get project secrets');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getSecrets;
|
||||
@@ -1,30 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This function uploads the encrypted .env file
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @returns
|
||||
*/
|
||||
const uploadSecrets = async ({ workspaceId, secrets, keys, environment }) => {
|
||||
return SecurityClient.fetchCall("/api/v1/secret/" + workspaceId, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
secrets,
|
||||
keys,
|
||||
environment,
|
||||
channel: "web",
|
||||
}),
|
||||
}).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to push secrets");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default uploadSecrets;
|
||||
@@ -0,0 +1,45 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
interface Props {
|
||||
workspaceId: string;
|
||||
secrets: any;
|
||||
keys: string;
|
||||
environment: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function uploads the encrypted .env file
|
||||
* @param {object} obj
|
||||
* @param {string} obj.workspaceId
|
||||
* @param {} obj.secrets
|
||||
* @param {} obj.keys
|
||||
* @param {string} obj.environment
|
||||
* @returns
|
||||
*/
|
||||
const uploadSecrets = async ({
|
||||
workspaceId,
|
||||
secrets,
|
||||
keys,
|
||||
environment
|
||||
}: Props) => {
|
||||
return SecurityClient.fetchCall('/api/v1/secret/' + workspaceId, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
secrets,
|
||||
keys,
|
||||
environment,
|
||||
channel: 'web'
|
||||
})
|
||||
}).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log('Failed to push secrets');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default uploadSecrets;
|
||||
@@ -1,25 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
const changeHerokuConfigVars = ({ integrationId, key, secrets }) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/integration/" + integrationId + "/sync",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
key,
|
||||
secrets,
|
||||
}),
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to sync secrets to Heroku");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default changeHerokuConfigVars;
|
||||
@@ -0,0 +1,41 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
interface Props {
|
||||
integrationId: string;
|
||||
key: { encryptedKey: any; nonce: any };
|
||||
secrets: {
|
||||
ciphertextKey: any;
|
||||
ivKey: any;
|
||||
tagKey: any;
|
||||
hashKey: any;
|
||||
ciphertextValue: any;
|
||||
ivValue: any;
|
||||
tagValue: any;
|
||||
hashValue: any;
|
||||
type: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
const changeHerokuConfigVars = ({ integrationId, key, secrets }: Props) => {
|
||||
return SecurityClient.fetchCall(
|
||||
'/api/v1/integration/' + integrationId + '/sync',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
key,
|
||||
secrets
|
||||
})
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log('Failed to sync secrets to Heroku');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default changeHerokuConfigVars;
|
||||
@@ -1,26 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This route deletes an integration from a certain project
|
||||
* @param {*} integrationId
|
||||
* @returns
|
||||
*/
|
||||
const deleteIntegration = ({ integrationId }) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/integration/" + integrationId,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return (await res.json()).workspace;
|
||||
} else {
|
||||
console.log("Failed to delete an integration");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default deleteIntegration;
|
||||
@@ -0,0 +1,27 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
interface Props {
|
||||
integrationId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This route deletes an integration from a certain project
|
||||
* @param {*} integrationId
|
||||
* @returns
|
||||
*/
|
||||
const deleteIntegration = ({ integrationId }: Props) => {
|
||||
return SecurityClient.fetchCall('/api/v1/integration/' + integrationId, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return (await res.json()).workspace;
|
||||
} else {
|
||||
console.log('Failed to delete an integration');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default deleteIntegration;
|
||||
@@ -1,26 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This route deletes an integration authorization from a certain project
|
||||
* @param {*} integrationAuthId
|
||||
* @returns
|
||||
*/
|
||||
const deleteIntegrationAuth = ({ integrationAuthId }) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/integration-auth/" + integrationAuthId,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to delete an integration authorization");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default deleteIntegrationAuth;
|
||||
@@ -0,0 +1,30 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
interface Props {
|
||||
integrationAuthId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This route deletes an integration authorization from a certain project
|
||||
* @param {*} integrationAuthId
|
||||
* @returns
|
||||
*/
|
||||
const deleteIntegrationAuth = ({ integrationAuthId }: Props) => {
|
||||
return SecurityClient.fetchCall(
|
||||
'/api/v1/integration-auth/' + integrationAuthId,
|
||||
{
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log('Failed to delete an integration authorization');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default deleteIntegrationAuth;
|
||||
@@ -1,21 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
const getIntegrationApps = ({ integrationAuthId }) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/integration-auth/" + integrationAuthId + "/apps",
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return (await res.json()).apps;
|
||||
} else {
|
||||
console.log("Failed to get available apps for an integration");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getIntegrationApps;
|
||||
@@ -0,0 +1,25 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
interface Props {
|
||||
integrationAuthId: string;
|
||||
}
|
||||
|
||||
const getIntegrationApps = ({ integrationAuthId }: Props) => {
|
||||
return SecurityClient.fetchCall(
|
||||
'/api/v1/integration-auth/' + integrationAuthId + '/apps',
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return (await res.json()).apps;
|
||||
} else {
|
||||
console.log('Failed to get available apps for an integration');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getIntegrationApps;
|
||||
@@ -1,18 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
const getIntegrations = () => {
|
||||
return SecurityClient.fetchCall("/api/v1/integration/integrations", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return (await res.json()).integrations;
|
||||
} else {
|
||||
console.log("Failed to get project integrations");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getIntegrations;
|
||||
@@ -0,0 +1,18 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
const getIntegrations = () => {
|
||||
return SecurityClient.fetchCall('/api/v1/integration/integrations', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return (await res.json()).integrations;
|
||||
} else {
|
||||
console.log('Failed to get project integrations');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getIntegrations;
|
||||
@@ -1,33 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This route starts the integration after teh default one if gonna set up.
|
||||
* @param {*} integrationId
|
||||
* @returns
|
||||
*/
|
||||
const startIntegration = ({ integrationId, appName, environment }) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/integration/" + integrationId,
|
||||
{
|
||||
method: "PATCH",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
update: {
|
||||
app: appName,
|
||||
environment,
|
||||
isActive: true,
|
||||
},
|
||||
}),
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to start an integration");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default startIntegration;
|
||||
@@ -0,0 +1,36 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
interface Props {
|
||||
integrationId: string;
|
||||
appName: string;
|
||||
environment: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This route starts the integration after teh default one if gonna set up.
|
||||
* @param {*} integrationId
|
||||
* @returns
|
||||
*/
|
||||
const startIntegration = ({ integrationId, appName, environment }: Props) => {
|
||||
return SecurityClient.fetchCall('/api/v1/integration/' + integrationId, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
update: {
|
||||
app: appName,
|
||||
environment,
|
||||
isActive: true
|
||||
}
|
||||
})
|
||||
}).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log('Failed to start an integration');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default startIntegration;
|
||||
@@ -1,31 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This is the first step of the change password process (pake)
|
||||
* @param {*} clientPublicKey
|
||||
* @returns
|
||||
*/
|
||||
const AuthorizeIntegration = ({ workspaceId, code, integration }) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/integration-auth/oauth-token",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
workspaceId,
|
||||
code,
|
||||
integration,
|
||||
}),
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to authorize the integration");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default AuthorizeIntegration;
|
||||
@@ -0,0 +1,36 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
interface Props {
|
||||
workspaceId: string;
|
||||
code: string;
|
||||
integration: string;
|
||||
}
|
||||
/**
|
||||
* This is the first step of the change password process (pake)
|
||||
* @param {object} obj
|
||||
* @param {object} obj.workspaceId - project id for which we want to authorize the integration
|
||||
* @param {object} obj.code
|
||||
* @param {object} obj.integration - integration which a user is trying to turn on
|
||||
* @returns
|
||||
*/
|
||||
const AuthorizeIntegration = ({ workspaceId, code, integration }: Props) => {
|
||||
return SecurityClient.fetchCall('/api/v1/integration-auth/oauth-token', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
workspaceId,
|
||||
code,
|
||||
integration
|
||||
})
|
||||
}).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log('Failed to authorize the integration');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default AuthorizeIntegration;
|
||||
@@ -1,26 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This route gets authorizations of a certain project (Heroku, etc.)
|
||||
* @param {*} workspaceId
|
||||
* @returns
|
||||
*/
|
||||
const getWorkspaceAuthorizations = ({ workspaceId }) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/workspace/" + workspaceId + "/authorizations",
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return (await res.json()).authorizations;
|
||||
} else {
|
||||
console.log("Failed to get project authorizations");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getWorkspaceAuthorizations;
|
||||
@@ -0,0 +1,30 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
interface Props {
|
||||
workspaceId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This route gets authorizations of a certain project (Heroku, etc.)
|
||||
* @param {*} workspaceId
|
||||
* @returns
|
||||
*/
|
||||
const getWorkspaceAuthorizations = ({ workspaceId }: Props) => {
|
||||
return SecurityClient.fetchCall(
|
||||
'/api/v1/workspace/' + workspaceId + '/authorizations',
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return (await res.json()).authorizations;
|
||||
} else {
|
||||
console.log('Failed to get project authorizations');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getWorkspaceAuthorizations;
|
||||
@@ -1,26 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This route gets integrations of a certain project (Heroku, etc.)
|
||||
* @param {*} workspaceId
|
||||
* @returns
|
||||
*/
|
||||
const getWorkspaceIntegrations = ({ workspaceId }) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/workspace/" + workspaceId + "/integrations",
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return (await res.json()).integrations;
|
||||
} else {
|
||||
console.log("Failed to get the project integrations");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getWorkspaceIntegrations;
|
||||
@@ -0,0 +1,30 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
interface Props {
|
||||
workspaceId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This route gets integrations of a certain project (Heroku, etc.)
|
||||
* @param {*} workspaceId
|
||||
* @returns
|
||||
*/
|
||||
const getWorkspaceIntegrations = ({ workspaceId }: Props) => {
|
||||
return SecurityClient.fetchCall(
|
||||
'/api/v1/workspace/' + workspaceId + '/integrations',
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return (await res.json()).integrations;
|
||||
} else {
|
||||
console.log('Failed to get the project integrations');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getWorkspaceIntegrations;
|
||||
@@ -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');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This route lets us get all the users in an org.
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @returns
|
||||
*/
|
||||
const getOrganizationProjects = (req, res) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/organization/" + req.orgId + "/workspaces",
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return (await res.json()).workspaces;
|
||||
} else {
|
||||
console.log("Failed to get projects for an org");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getOrganizationProjects;
|
||||
@@ -0,0 +1,29 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This route lets us get all the users in an org.
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @returns
|
||||
*/
|
||||
|
||||
// TODO: this file is not used anywhere
|
||||
const getOrganizationProjects = (req: { orgId: string }) => {
|
||||
return SecurityClient.fetchCall(
|
||||
'/api/organization/' + req.orgId + '/workspaces',
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return (await res.json()).workspaces;
|
||||
} else {
|
||||
console.log('Failed to get projects for an org');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getOrganizationProjects;
|
||||
@@ -1,27 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This route lets us get the current subscription of an org.
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @returns
|
||||
*/
|
||||
const getOrganizationSubscriptions = (req, res) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/organization/" + req.orgId + "/subscriptions",
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return (await res.json()).subscriptions;
|
||||
} else {
|
||||
console.log("Failed to get org subscriptions");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getOrganizationSubscriptions;
|
||||
@@ -0,0 +1,27 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This route lets us get the current subscription of an org.
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @returns
|
||||
*/
|
||||
const getOrganizationSubscriptions = (req: { orgId: string }) => {
|
||||
return SecurityClient.fetchCall(
|
||||
'/api/v1/organization/' + req.orgId + '/subscriptions',
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return (await res.json()).subscriptions;
|
||||
} else {
|
||||
console.log('Failed to get org subscriptions');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getOrganizationSubscriptions;
|
||||
@@ -1,27 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This route lets us get all the projects of a certain user in an org.
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @returns
|
||||
*/
|
||||
const getOrganizationUserProjects = (req) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/organization/" + req.orgId + "/my-workspaces",
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return (await res.json()).workspaces;
|
||||
} else {
|
||||
console.log("Failed to get projects of a user in an org");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getOrganizationUserProjects;
|
||||
@@ -0,0 +1,27 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This route lets us get all the projects of a certain user in an org.
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @returns
|
||||
*/
|
||||
const getOrganizationUserProjects = (req: { orgId: string }) => {
|
||||
return SecurityClient.fetchCall(
|
||||
'/api/v1/organization/' + req.orgId + '/my-workspaces',
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return (await res.json()).workspaces;
|
||||
} else {
|
||||
console.log('Failed to get projects of a user in an org');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getOrganizationUserProjects;
|
||||
@@ -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');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This route redirects the user to the right stripe billing page.
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @returns
|
||||
*/
|
||||
const StripeRedirect = ({ orgId }) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/organization/" + orgId + "/customer-portal-session",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return (window.location.href = (await res.json()).url);
|
||||
} else {
|
||||
console.log("Failed to redirect to Stripe");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default StripeRedirect;
|
||||
@@ -0,0 +1,27 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This route redirects the user to the right stripe billing page.
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @returns
|
||||
*/
|
||||
const StripeRedirect = ({ orgId }: { orgId: string }) => {
|
||||
return SecurityClient.fetchCall(
|
||||
'/api/v1/organization/' + orgId + '/customer-portal-session',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return (window.location.href = (await res.json()).url);
|
||||
} else {
|
||||
console.log('Failed to redirect to Stripe');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default StripeRedirect;
|
||||
@@ -1,29 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This route add an incident contact email to a certain organization
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
const addIncidentContact = (organizationId, email) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/organization/" + organizationId + "/incidentContactOrg",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: email,
|
||||
}),
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to add an incident contact");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default addIncidentContact;
|
||||
@@ -0,0 +1,29 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This route add an incident contact email to a certain organization
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
const addIncidentContact = (organizationId: string, email: string) => {
|
||||
return SecurityClient.fetchCall(
|
||||
'/api/v1/organization/' + organizationId + '/incidentContactOrg',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: email
|
||||
})
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log('Failed to add an incident contact');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default addIncidentContact;
|
||||
@@ -1,28 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This function sends an email invite to a user to join an org
|
||||
* @param {*} email
|
||||
* @param {*} orgId
|
||||
* @returns
|
||||
*/
|
||||
const addUserToOrg = (email, orgId) => {
|
||||
return SecurityClient.fetchCall("/api/v1/invite-org/signup", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
inviteeEmail: email,
|
||||
organizationId: orgId,
|
||||
}),
|
||||
}).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to add a user to an org");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default addUserToOrg;
|
||||
@@ -0,0 +1,28 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This function sends an email invite to a user to join an org
|
||||
* @param {*} email
|
||||
* @param {*} orgId
|
||||
* @returns
|
||||
*/
|
||||
const addUserToOrg = (email: string, orgId: string) => {
|
||||
return SecurityClient.fetchCall('/api/v1/invite-org/signup', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
inviteeEmail: email,
|
||||
organizationId: orgId
|
||||
})
|
||||
}).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log('Failed to add a user to an org');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default addUserToOrg;
|
||||
@@ -1,29 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This route deletes an incident Contact from a certain organization
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
const deleteIncidentContact = (organizaionId, email) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/organization/" + organizaionId + "/incidentContactOrg",
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: email,
|
||||
}),
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to delete an incident contact");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default deleteIncidentContact;
|
||||
@@ -0,0 +1,29 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This route deletes an incident Contact from a certain organization
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
const deleteIncidentContact = (organizationId: string, email: string) => {
|
||||
return SecurityClient.fetchCall(
|
||||
'/api/v1/organization/' + organizationId + '/incidentContactOrg',
|
||||
{
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: email
|
||||
})
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log('Failed to delete an incident contact');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default deleteIncidentContact;
|
||||
@@ -1,26 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This function removes a certain member from a certain organization
|
||||
* @param {*} membershipId
|
||||
* @returns
|
||||
*/
|
||||
const deleteUserFromOrganization = (membershipId) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/membership-org/" + membershipId,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to delete a user from an org");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default deleteUserFromOrganization;
|
||||
@@ -0,0 +1,23 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This function removes a certain member from a certain organization
|
||||
* @param {*} membershipId
|
||||
* @returns
|
||||
*/
|
||||
const deleteUserFromOrganization = (membershipId: string) => {
|
||||
return SecurityClient.fetchCall('/api/v1/membership-org/' + membershipId, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log('Failed to delete a user from an org');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default deleteUserFromOrganization;
|
||||
@@ -1,26 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This routes gets all the incident contacts of a certain organization
|
||||
* @param {*} workspaceId
|
||||
* @returns
|
||||
*/
|
||||
const getIncidentContacts = (organizationId) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/organization/" + organizationId + "/incidentContactOrg",
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return (await res.json()).incidentContactsOrg;
|
||||
} else {
|
||||
console.log("Failed to get incident contacts");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getIncidentContacts;
|
||||
@@ -0,0 +1,26 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This routes gets all the incident contacts of a certain organization
|
||||
* @param {*} workspaceId
|
||||
* @returns
|
||||
*/
|
||||
const getIncidentContacts = (organizationId: string) => {
|
||||
return SecurityClient.fetchCall(
|
||||
'/api/v1/organization/' + organizationId + '/incidentContactOrg',
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return (await res.json()).incidentContactsOrg;
|
||||
} else {
|
||||
console.log('Failed to get incident contacts');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getIncidentContacts;
|
||||
@@ -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');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This route lets us rename a certain org.
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @returns
|
||||
*/
|
||||
const renameOrg = (orgId, newOrgName) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/organization/" + orgId + "/name",
|
||||
{
|
||||
method: "PATCH",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: newOrgName,
|
||||
}),
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to rename an organization");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default renameOrg;
|
||||
@@ -0,0 +1,27 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This route lets us rename a certain org.
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @returns
|
||||
*/
|
||||
const renameOrg = (orgId: string, newOrgName: string) => {
|
||||
return SecurityClient.fetchCall('/api/v1/organization/' + orgId + '/name', {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: newOrgName
|
||||
})
|
||||
}).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log('Failed to rename an organization');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default renameOrg;
|
||||
+20
-10
@@ -1,4 +1,14 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
interface Props {
|
||||
name: string;
|
||||
workspaceId: string;
|
||||
environment: string;
|
||||
expiresIn: number;
|
||||
publicKey: string;
|
||||
encryptedKey: string;
|
||||
nonce: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This route gets service tokens for a specific user in a project
|
||||
@@ -12,12 +22,12 @@ const addServiceToken = ({
|
||||
expiresIn,
|
||||
publicKey,
|
||||
encryptedKey,
|
||||
nonce,
|
||||
}) => {
|
||||
return SecurityClient.fetchCall("/api/v1/service-token/", {
|
||||
method: "POST",
|
||||
nonce
|
||||
}: Props) => {
|
||||
return SecurityClient.fetchCall('/api/v1/service-token/', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name,
|
||||
@@ -26,13 +36,13 @@ const addServiceToken = ({
|
||||
expiresIn,
|
||||
publicKey,
|
||||
encryptedKey,
|
||||
nonce,
|
||||
}),
|
||||
nonce
|
||||
})
|
||||
}).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
if (res && res.status == 200) {
|
||||
return (await res.json()).token;
|
||||
} else {
|
||||
console.log("Failed to add service tokens");
|
||||
console.log('Failed to add service tokens');
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -1,26 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This route gets service tokens for a specific user in a project
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
const getServiceTokens = ({ workspaceId }) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/workspace/" + workspaceId + "/service-tokens",
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return (await res.json()).serviceTokens;
|
||||
} else {
|
||||
console.log("Failed to get service tokens");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getServiceTokens;
|
||||
@@ -0,0 +1,26 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This route gets service tokens for a specific user in a project
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
const getServiceTokens = ({ workspaceId }: { workspaceId: string }) => {
|
||||
return SecurityClient.fetchCall(
|
||||
'/api/v1/workspace/' + workspaceId + '/service-tokens',
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return (await res.json()).serviceTokens;
|
||||
} else {
|
||||
console.log('Failed to get service tokens');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default getServiceTokens;
|
||||
@@ -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');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
+10
-10
@@ -1,4 +1,4 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This route registers a certain action for a user
|
||||
@@ -6,24 +6,24 @@ import SecurityClient from "~/utilities/SecurityClient";
|
||||
* @param {*} workspaceId
|
||||
* @returns
|
||||
*/
|
||||
const checkUserAction = ({ action }) => {
|
||||
const checkUserAction = ({ action }: { action: string }) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/user-action" +
|
||||
"?" +
|
||||
'/api/v1/user-action' +
|
||||
'?' +
|
||||
new URLSearchParams({
|
||||
action,
|
||||
action
|
||||
}),
|
||||
{
|
||||
method: "GET",
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
if (res && res.status == 200) {
|
||||
return (await res.json()).userAction;
|
||||
} else {
|
||||
console.log("Failed to check a user action");
|
||||
console.log('Failed to check a user action');
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -1,26 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This route registers a certain action for a user
|
||||
* @param {*} action
|
||||
* @returns
|
||||
*/
|
||||
const registerUserAction = ({ action }) => {
|
||||
return SecurityClient.fetchCall("/api/v1/user-action", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
action,
|
||||
}),
|
||||
}).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to register a user action");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default registerUserAction;
|
||||
@@ -0,0 +1,26 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This route registers a certain action for a user
|
||||
* @param {*} action
|
||||
* @returns
|
||||
*/
|
||||
const registerUserAction = ({ action }: { action: string }) => {
|
||||
return SecurityClient.fetchCall('/api/v1/user-action', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
action
|
||||
})
|
||||
}).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log('Failed to register a user action');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default registerUserAction;
|
||||
@@ -1,30 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This function adds a user to a project
|
||||
* @param {*} email
|
||||
* @param {*} workspaceId
|
||||
* @returns
|
||||
*/
|
||||
const addUserToWorkspace = (email, workspaceId) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/workspace/" + workspaceId + "/invite-signup",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: email,
|
||||
}),
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return await res.json();
|
||||
} else {
|
||||
console.log("Failed to add a user to project");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default addUserToWorkspace;
|
||||
@@ -0,0 +1,30 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This function adds a user to a project
|
||||
* @param {*} email
|
||||
* @param {*} workspaceId
|
||||
* @returns
|
||||
*/
|
||||
const addUserToWorkspace = (email: string, workspaceId: string) => {
|
||||
return SecurityClient.fetchCall(
|
||||
'/api/v1/workspace/' + workspaceId + '/invite-signup',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: email
|
||||
})
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return await res.json();
|
||||
} else {
|
||||
console.log('Failed to add a user to project');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default addUserToWorkspace;
|
||||
@@ -1,30 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This function change the access of a user in a certain workspace
|
||||
* @param {*} membershipId
|
||||
* @param {*} role
|
||||
* @returns
|
||||
*/
|
||||
const changeUserRoleInWorkspace = (membershipId, role) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/membership/" + membershipId + "/change-role",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
role: role,
|
||||
}),
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to change the user role in a project");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default changeUserRoleInWorkspace;
|
||||
@@ -0,0 +1,30 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This function change the access of a user in a certain workspace
|
||||
* @param {*} membershipId
|
||||
* @param {*} role
|
||||
* @returns
|
||||
*/
|
||||
const changeUserRoleInWorkspace = (membershipId: string, role: string) => {
|
||||
return SecurityClient.fetchCall(
|
||||
'/api/v1/membership/' + membershipId + '/change-role',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
role: role
|
||||
})
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log('Failed to change the user role in a project');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default changeUserRoleInWorkspace;
|
||||
@@ -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,23 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This function removes a certain member from a certain workspace
|
||||
* @param {*} membershipId
|
||||
* @returns
|
||||
*/
|
||||
const deleteUserFromWorkspace = (membershipId) => {
|
||||
return SecurityClient.fetchCall("/api/v1/membership/" + membershipId, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to delete a user from a project");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default deleteUserFromWorkspace;
|
||||
@@ -0,0 +1,23 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This function removes a certain member from a certain workspace
|
||||
* @param {*} membershipId
|
||||
* @returns
|
||||
*/
|
||||
const deleteUserFromWorkspace = (membershipId: string) => {
|
||||
return SecurityClient.fetchCall('/api/v1/membership/' + membershipId, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log('Failed to delete a user from a project');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default deleteUserFromWorkspace;
|
||||
@@ -1,23 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This route deletes a specified workspace.
|
||||
* @param {*} workspaceId
|
||||
* @returns
|
||||
*/
|
||||
const deleteWorkspace = (workspaceId) => {
|
||||
return SecurityClient.fetchCall("/api/v1/workspace/" + workspaceId, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to delete a project");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default deleteWorkspace;
|
||||
@@ -0,0 +1,23 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This route deletes a specified workspace.
|
||||
* @param {*} workspaceId
|
||||
* @returns
|
||||
*/
|
||||
const deleteWorkspace = (workspaceId: string) => {
|
||||
return SecurityClient.fetchCall('/api/v1/workspace/' + workspaceId, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log('Failed to delete a project');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default deleteWorkspace;
|
||||
@@ -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');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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');
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This route lets us rename a certain workspace.
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @returns
|
||||
*/
|
||||
const renameWorkspace = (workspaceId, newWorkspaceName) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/workspace/" + workspaceId + "/name",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: newWorkspaceName,
|
||||
}),
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to rename a project");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default renameWorkspace;
|
||||
@@ -0,0 +1,30 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This route lets us rename a certain workspace.
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @returns
|
||||
*/
|
||||
const renameWorkspace = (workspaceId: string, newWorkspaceName: string) => {
|
||||
return SecurityClient.fetchCall(
|
||||
'/api/v1/workspace/' + workspaceId + '/name',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: newWorkspaceName
|
||||
})
|
||||
}
|
||||
).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log('Failed to rename a project');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default renameWorkspace;
|
||||
@@ -1,33 +0,0 @@
|
||||
import SecurityClient from "~/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* This route uplods the keys in an encrypted format.
|
||||
* @param {*} workspaceId
|
||||
* @param {*} userId
|
||||
* @param {*} encryptedKey
|
||||
* @param {*} nonce
|
||||
* @returns
|
||||
*/
|
||||
const uploadKeys = (workspaceId, userId, encryptedKey, nonce) => {
|
||||
return SecurityClient.fetchCall("/api/v1/key/" + workspaceId, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
key: {
|
||||
userId: userId,
|
||||
encryptedKey: encryptedKey,
|
||||
nonce: nonce,
|
||||
},
|
||||
}),
|
||||
}).then(async (res) => {
|
||||
if (res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log("Failed to upload keys for a new user");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default uploadKeys;
|
||||
@@ -0,0 +1,38 @@
|
||||
import SecurityClient from '~/utilities/SecurityClient';
|
||||
|
||||
/**
|
||||
* This route uplods the keys in an encrypted format.
|
||||
* @param {*} workspaceId
|
||||
* @param {*} userId
|
||||
* @param {*} encryptedKey
|
||||
* @param {*} nonce
|
||||
* @returns
|
||||
*/
|
||||
const uploadKeys = (
|
||||
workspaceId: string,
|
||||
userId: string,
|
||||
encryptedKey: string,
|
||||
nonce: string
|
||||
) => {
|
||||
return SecurityClient.fetchCall('/api/v1/key/' + workspaceId, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
key: {
|
||||
userId: userId,
|
||||
encryptedKey: encryptedKey,
|
||||
nonce: nonce
|
||||
}
|
||||
})
|
||||
}).then(async (res) => {
|
||||
if (res && res.status == 200) {
|
||||
return res;
|
||||
} else {
|
||||
console.log('Failed to upload keys for a new user');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default uploadKeys;
|
||||
@@ -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);
|
||||
|
||||
@@ -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]);
|
||||
@@ -281,13 +281,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);
|
||||
@@ -297,7 +297,7 @@ export default function Dashboard() {
|
||||
setFileState,
|
||||
setIsKeyAvailable,
|
||||
setData,
|
||||
workspaceId: router.query.id,
|
||||
workspaceId: router.query.id
|
||||
});
|
||||
|
||||
const user = await getUser();
|
||||
@@ -308,11 +308,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([]);
|
||||
}
|
||||
})();
|
||||
@@ -395,15 +395,15 @@ export default function Dashboard() {
|
||||
|
||||
if (nameErrors) {
|
||||
return createNotification({
|
||||
text: "Solve all name errors first!",
|
||||
type: "error",
|
||||
text: 'Solve all name errors before saving secrets.',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
|
||||
if (duplicatesExist) {
|
||||
return createNotification({
|
||||
text: "Your secrets weren't saved; please fix the conflicts first.",
|
||||
type: "error",
|
||||
text: 'Remove duplicated secret names before saving.',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
|
||||
@@ -416,7 +416,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 (
|
||||
@@ -429,7 +429,7 @@ export default function Dashboard() {
|
||||
);
|
||||
await pushKeysIntegration({
|
||||
obj: objIntegration,
|
||||
integrationId: integration._id,
|
||||
integrationId: integration._id
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -437,7 +437,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' });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -452,7 +452,7 @@ export default function Dashboard() {
|
||||
|
||||
const sortValuesHandler = () => {
|
||||
const sortedData = data.sort((a, b) =>
|
||||
sortMethod == "alphabetical"
|
||||
sortMethod == 'alphabetical'
|
||||
? a.key.localeCompare(b.key)
|
||||
: b.key.localeCompare(a.key)
|
||||
).map((item, index) => {
|
||||
@@ -466,12 +466,12 @@ export default function Dashboard() {
|
||||
|
||||
// This function downloads the secrets as a .env file
|
||||
const download = () => {
|
||||
const file = data.map((item) => [item.key, item.value].join("=")).join("\n");
|
||||
const file = data.map((item) => [item.key, item.value].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();
|
||||
};
|
||||
|
||||
@@ -483,7 +483,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
|
||||
@@ -526,7 +526,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"
|
||||
@@ -581,7 +581,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"
|
||||
@@ -595,7 +595,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">
|
||||
@@ -604,7 +604,7 @@ export default function Dashboard() {
|
||||
color="mineshaft"
|
||||
size="icon-md"
|
||||
icon={
|
||||
sortMethod == "alphabetical"
|
||||
sortMethod == 'alphabetical'
|
||||
? faArrowDownAZ
|
||||
: faArrowDownZA
|
||||
}
|
||||
@@ -675,7 +675,7 @@ export default function Dashboard() {
|
||||
keyPair.key
|
||||
.toLowerCase()
|
||||
.includes(searchKeys.toLowerCase()) &&
|
||||
keyPair.type == "personal"
|
||||
keyPair.type == 'personal'
|
||||
)?.map((keyPair) => (
|
||||
<KeyPair
|
||||
key={keyPair.id}
|
||||
@@ -698,7 +698,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">
|
||||
@@ -723,7 +723,7 @@ export default function Dashboard() {
|
||||
keyPair.key
|
||||
.toLowerCase()
|
||||
.includes(searchKeys.toLowerCase()) &&
|
||||
keyPair.type == "shared"
|
||||
keyPair.type == 'shared'
|
||||
)?.map((keyPair) => (
|
||||
<KeyPair
|
||||
key={keyPair.id}
|
||||
@@ -778,10 +778,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
|
||||
|
||||
+169
-83
@@ -1,92 +1,134 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import { IconProp } from "@fortawesome/fontawesome-svg-core";
|
||||
import { faSlack } from "@fortawesome/free-brands-svg-icons";
|
||||
import { faCheckCircle, faHandPeace, faNetworkWired, faPlug, faPlus, faStar, faUserPlus } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
import { IconProp } from '@fortawesome/fontawesome-svg-core';
|
||||
import { faSlack } from '@fortawesome/free-brands-svg-icons';
|
||||
import {
|
||||
faCheckCircle,
|
||||
faHandPeace,
|
||||
faNetworkWired,
|
||||
faPlug,
|
||||
faPlus,
|
||||
faStar,
|
||||
faUserPlus
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
|
||||
import getOrganizationUsers from "../api/organization/GetOrgUsers";
|
||||
import checkUserAction from "../api/userActions/checkUserAction";
|
||||
import registerUserAction from "../api/userActions/registerUserAction";
|
||||
import onboardingCheck from '~/components/utilities/checks/OnboardingCheck';
|
||||
|
||||
type ItemProps = {
|
||||
text: string;
|
||||
subText: string;
|
||||
complete: boolean;
|
||||
icon: IconProp;
|
||||
time: string;
|
||||
import registerUserAction from '../api/userActions/registerUserAction';
|
||||
|
||||
type ItemProps = {
|
||||
text: string;
|
||||
subText: string;
|
||||
complete: boolean;
|
||||
icon: IconProp;
|
||||
time: string;
|
||||
userAction?: string;
|
||||
link?: string;
|
||||
};
|
||||
|
||||
const learningItem = ({ text, subText, complete, icon, time, userAction, link }: ItemProps): JSX.Element => {
|
||||
const learningItem = ({
|
||||
text,
|
||||
subText,
|
||||
complete,
|
||||
icon,
|
||||
time,
|
||||
userAction,
|
||||
link
|
||||
}: ItemProps): JSX.Element => {
|
||||
if (link) {
|
||||
return (
|
||||
<Link href={link}>
|
||||
<a target={`${link.includes("https") ? "_blank" : "_self"}`} rel="noopener noreferrer" className="w-full">
|
||||
<div
|
||||
onClick={async () => {
|
||||
if (userAction) {
|
||||
await registerUserAction({
|
||||
action: userAction
|
||||
})
|
||||
<a
|
||||
target={`${link.includes('https') ? '_blank' : '_self'}`}
|
||||
rel="noopener noreferrer"
|
||||
className="w-full"
|
||||
>
|
||||
<div
|
||||
onClick={async () => {
|
||||
if (userAction && userAction != 'first_time_secrets_pushed') {
|
||||
await registerUserAction({
|
||||
action: userAction
|
||||
});
|
||||
}
|
||||
}}
|
||||
className="relative bg-bunker-700 hover:bg-bunker-500 shadow-xl duration-200 rounded-md border border-dashed border-bunker-400 pl-2 pr-6 py-2 h-[5.5rem] w-full flex items-center justify-between overflow-hidden my-1.5 cursor-pointer">
|
||||
className="relative bg-bunker-700 hover:bg-bunker-500 shadow-xl duration-200 rounded-md border border-dashed border-bunker-400 pl-2 pr-6 py-2 h-[5.5rem] w-full flex items-center justify-between overflow-hidden my-1.5 cursor-pointer"
|
||||
>
|
||||
<div className="flex flex-row items-center mr-4">
|
||||
<FontAwesomeIcon icon={icon} className="text-4xl mx-2 w-16" />
|
||||
{complete &&
|
||||
<div className="bg-bunker-700 w-7 h-7 rounded-full absolute left-11 top-10 p-2 flex items-center justify-center">
|
||||
<FontAwesomeIcon icon={faCheckCircle} className="text-4xl w-5 h-5 text-green" />
|
||||
</div>}
|
||||
{complete && (
|
||||
<div className="bg-bunker-700 w-7 h-7 rounded-full absolute left-12 top-10 p-2 flex items-center justify-center">
|
||||
<FontAwesomeIcon
|
||||
icon={faCheckCircle}
|
||||
className="text-4xl w-5 h-5 text-green"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col items-start">
|
||||
<div className="text-xl font-semibold mt-0.5">{text}</div>
|
||||
<div className="text-sm font-normal">{subText}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`pr-4 font-semibold text-sm w-28 text-right ${complete && "text-green"}`}>
|
||||
{complete ? "Complete!" : "About " + time}
|
||||
<div
|
||||
className={`pr-4 font-semibold text-sm w-28 text-right ${
|
||||
complete && 'text-green'
|
||||
}`}
|
||||
>
|
||||
{complete ? 'Complete!' : 'About ' + time}
|
||||
</div>
|
||||
{complete && <div className="absolute bottom-0 left-0 h-1 w-full bg-green"></div>}
|
||||
{complete && (
|
||||
<div className="absolute bottom-0 left-0 h-1 w-full bg-green"></div>
|
||||
)}
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div
|
||||
onClick={async () => {
|
||||
if (userAction) {
|
||||
await registerUserAction({
|
||||
action: userAction
|
||||
})
|
||||
}
|
||||
}}
|
||||
className="relative bg-bunker-700 hover:bg-bunker-500 shadow-xl duration-200 rounded-md border border-dashed border-bunker-400 pl-2 pr-6 py-2 h-[5.5rem] w-full flex items-center justify-between overflow-hidden my-1.5 cursor-pointer">
|
||||
<div
|
||||
onClick={async () => {
|
||||
if (userAction) {
|
||||
await registerUserAction({
|
||||
action: userAction
|
||||
});
|
||||
}
|
||||
}}
|
||||
className="relative bg-bunker-700 hover:bg-bunker-500 shadow-xl duration-200 rounded-md border border-dashed border-bunker-400 pl-2 pr-6 py-2 h-[5.5rem] w-full flex items-center justify-between overflow-hidden my-1.5 cursor-pointer"
|
||||
>
|
||||
<div className="flex flex-row items-center mr-4">
|
||||
<FontAwesomeIcon icon={icon} className="text-4xl mx-2 w-16" />
|
||||
{complete &&
|
||||
<div className="bg-bunker-700 w-7 h-7 rounded-full absolute left-11 top-10">
|
||||
<FontAwesomeIcon icon={faCheckCircle} className="absolute text-4xl left-12 top-16 w-5 h-5 text-green" />
|
||||
</div>}
|
||||
{complete && (
|
||||
<div className="bg-bunker-700 w-7 h-7 rounded-full absolute left-11 top-10">
|
||||
<FontAwesomeIcon
|
||||
icon={faCheckCircle}
|
||||
className="absolute text-4xl left-12 top-16 w-5 h-5 text-green"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col items-start">
|
||||
<div className="text-xl font-semibold mt-0.5">{text}</div>
|
||||
<div className="text-sm font-normal mt-0.5">{subText}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`pr-4 font-semibold text-sm w-28 text-right ${complete && "text-green"}`}>
|
||||
{complete ? "Complete!" : "About " + time}
|
||||
<div
|
||||
className={`pr-4 font-semibold text-sm w-28 text-right ${
|
||||
complete && 'text-green'
|
||||
}`}
|
||||
>
|
||||
{complete ? 'Complete!' : 'About ' + time}
|
||||
</div>
|
||||
{complete && <div className="absolute bottom-0 left-0 h-1 w-full bg-green"></div>}
|
||||
{complete && (
|
||||
<div className="absolute bottom-0 left-0 h-1 w-full bg-green"></div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This tab is called Home because in the future it will include some company news,
|
||||
* updates, roadmap, relavant blogs, etc. Currently it only has the setup instruction
|
||||
* This tab is called Home because in the future it will include some company news,
|
||||
* updates, roadmap, relavant blogs, etc. Currently it only has the setup instruction
|
||||
* for the new users
|
||||
*/
|
||||
export default function Home() {
|
||||
@@ -94,46 +136,90 @@ export default function Home() {
|
||||
const [hasUserClickedSlack, setHasUserClickedSlack] = useState(false);
|
||||
const [hasUserClickedIntro, setHasUserClickedIntro] = useState(false);
|
||||
const [hasUserStarred, setHasUserStarred] = useState(false);
|
||||
const [hasUserPushedSecrets, setHasUserPushedSecrets] = useState(false);
|
||||
const [usersInOrg, setUsersInOrg] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const checkUserActionsFunction = async () => {
|
||||
const userActionSlack = await checkUserAction({
|
||||
action: "slack_cta_clicked",
|
||||
});
|
||||
setHasUserClickedSlack(userActionSlack ? true : false);
|
||||
|
||||
const userActionIntro = await checkUserAction({
|
||||
action: "intro_cta_clicked",
|
||||
});
|
||||
setHasUserClickedIntro(userActionIntro ? true : false);
|
||||
|
||||
const userActionStar = await checkUserAction({
|
||||
action: "star_cta_clicked",
|
||||
});
|
||||
setHasUserStarred(userActionStar ? true : false);
|
||||
|
||||
const orgId = localStorage.getItem("orgData.id");
|
||||
const orgUsers = await getOrganizationUsers({
|
||||
orgId: orgId ? orgId : "",
|
||||
});
|
||||
setUsersInOrg(orgUsers.length > 1)
|
||||
};
|
||||
checkUserActionsFunction();
|
||||
onboardingCheck({
|
||||
setHasUserClickedIntro,
|
||||
setHasUserClickedSlack,
|
||||
setHasUserPushedSecrets,
|
||||
setHasUserStarred,
|
||||
setUsersInOrg
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="mx-6 lg:mx-0 w-full overflow-y-scroll pt-20 h-screen">
|
||||
<div className="flex flex-col items-center text-gray-300 text-lg mx-auto max-w-2xl lg:max-w-3xl xl:max-w-4xl py-6">
|
||||
<div className="text-3xl font-bold text-left w-full">Your quick start guide</div>
|
||||
<div className="text-md text-left w-full pt-2 pb-4 text-bunker-300">Click on the items below and follow the instructions.</div>
|
||||
{learningItem({ text: "Get to know Infisical", subText: "", complete: hasUserClickedIntro, icon: faHandPeace, time: "3 min", userAction: "intro_cta_clicked", link: "https://www.youtube.com/watch?v=JS3OKYU2078" })}
|
||||
{learningItem({ text: "Add your secrets", subText: "Click to see example secrets, and add your own.", complete: false, icon: faPlus, time: "2 min", userAction: "first_time_secrets_pushed", link: "/dashboard/" + router.query.id })}
|
||||
{learningItem({ text: "Inject secrets locally", subText: "Replace .env files with a more secure an efficient alternative.", complete: false, icon: faNetworkWired, time: "8 min", link: "https://infisical.com/docs/getting-started/quickstart" })}
|
||||
{learningItem({ text: "Integrate Infisical with your infrastructure", subText: "Only a few integrations are currently available. Many more coming soon!", complete: false, icon: faPlug, time: "15 min", link: "https://infisical.com/docs/integrations/overview" })}
|
||||
{learningItem({ text: "Invite your teammates", subText: "", complete: usersInOrg, icon: faUserPlus, time: "2 min", link: "/settings/org/" + router.query.id + "?invite" })}
|
||||
{learningItem({ text: "Join Infisical Slack", subText: "Have any questions? Ask us!", complete: hasUserClickedSlack, icon: faSlack, time: "1 min", userAction: "slack_cta_clicked", link: "https://join.slack.com/t/infisical-users/shared_invite/zt-1kdbk07ro-RtoyEt_9E~fyzGo_xQYP6g" })}
|
||||
{learningItem({ text: "Star Infisical on GitHub", subText: "Like what we're doing? You know what to do! :)", complete: hasUserStarred, icon: faStar, time: "1 min", userAction: "star_cta_clicked", link: "https://github.com/Infisical/infisical" })}
|
||||
<div className="text-3xl font-bold text-left w-full">
|
||||
Your quick start guide
|
||||
</div>
|
||||
<div className="text-md text-left w-full pt-2 pb-4 text-bunker-300">
|
||||
Click on the items below and follow the instructions.
|
||||
</div>
|
||||
{learningItem({
|
||||
text: 'Get to know Infisical',
|
||||
subText: '',
|
||||
complete: hasUserClickedIntro,
|
||||
icon: faHandPeace,
|
||||
time: '3 min',
|
||||
userAction: 'intro_cta_clicked',
|
||||
link: 'https://www.youtube.com/watch?v=JS3OKYU2078'
|
||||
})}
|
||||
{learningItem({
|
||||
text: 'Add your secrets',
|
||||
subText: 'Click to see example secrets, and add your own.',
|
||||
complete: hasUserPushedSecrets,
|
||||
icon: faPlus,
|
||||
time: '2 min',
|
||||
userAction: 'first_time_secrets_pushed',
|
||||
link: '/dashboard/' + router.query.id
|
||||
})}
|
||||
{learningItem({
|
||||
text: 'Inject secrets locally',
|
||||
subText:
|
||||
'Replace .env files with a more secure an efficient alternative.',
|
||||
complete: false,
|
||||
icon: faNetworkWired,
|
||||
time: '8 min',
|
||||
link: 'https://infisical.com/docs/getting-started/quickstart'
|
||||
})}
|
||||
{learningItem({
|
||||
text: 'Integrate Infisical with your infrastructure',
|
||||
subText:
|
||||
'Only a few integrations are currently available. Many more coming soon!',
|
||||
complete: false,
|
||||
icon: faPlug,
|
||||
time: '15 min',
|
||||
link: 'https://infisical.com/docs/integrations/overview'
|
||||
})}
|
||||
{learningItem({
|
||||
text: 'Invite your teammates',
|
||||
subText: '',
|
||||
complete: usersInOrg,
|
||||
icon: faUserPlus,
|
||||
time: '2 min',
|
||||
link: '/settings/org/' + router.query.id + '?invite'
|
||||
})}
|
||||
{learningItem({
|
||||
text: 'Join Infisical Slack',
|
||||
subText: 'Have any questions? Ask us!',
|
||||
complete: hasUserClickedSlack,
|
||||
icon: faSlack,
|
||||
time: '1 min',
|
||||
userAction: 'slack_cta_clicked',
|
||||
link: 'https://join.slack.com/t/infisical-users/shared_invite/zt-1kdbk07ro-RtoyEt_9E~fyzGo_xQYP6g'
|
||||
})}
|
||||
{learningItem({
|
||||
text: 'Star Infisical on GitHub',
|
||||
subText: "Like what we're doing? You know what to do! :)",
|
||||
complete: hasUserStarred,
|
||||
icon: faStar,
|
||||
time: '1 min',
|
||||
userAction: 'star_cta_clicked',
|
||||
link: 'https://github.com/Infisical/infisical'
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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) =>
|
||||
|
||||
+85
-86
@@ -1,72 +1,71 @@
|
||||
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, useState } from 'react';
|
||||
import ReactCodeInput from 'react-code-input';
|
||||
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 +76,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 +108,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 +127,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 +169,7 @@ export default function SignUp() {
|
||||
setPasswordErrorLength,
|
||||
setPasswordErrorNumber,
|
||||
setPasswordErrorLowerCase,
|
||||
currentErrorCheck: errorCheck,
|
||||
currentErrorCheck: errorCheck
|
||||
});
|
||||
|
||||
if (!errorCheck) {
|
||||
@@ -181,22 +180,22 @@ export default function SignUp() {
|
||||
const PRIVATE_KEY = nacl.util.encodeBase64(secretKeyUint8Array);
|
||||
const PUBLIC_KEY = nacl.util.encodeBase64(publicKeyUint8Array);
|
||||
|
||||
const { ciphertext, iv, tag } = Aes256Gcm.encrypt(
|
||||
PRIVATE_KEY,
|
||||
password
|
||||
const { ciphertext, iv, tag } = Aes256Gcm.encrypt({
|
||||
text: PRIVATE_KEY,
|
||||
secret: password
|
||||
.slice(0, 32)
|
||||
.padStart(
|
||||
32 + (password.slice(0, 32).length - new Blob([password]).size),
|
||||
"0"
|
||||
'0'
|
||||
)
|
||||
) as { ciphertext: string; iv: string; tag: string };
|
||||
}) 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 +211,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 +294,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 +382,7 @@ export default function SignUp() {
|
||||
setPasswordErrorLength,
|
||||
setPasswordErrorNumber,
|
||||
setPasswordErrorLowerCase,
|
||||
currentErrorCheck: false,
|
||||
currentErrorCheck: false
|
||||
});
|
||||
}}
|
||||
type="password"
|
||||
@@ -416,7 +415,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 +435,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 +455,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 +504,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"
|
||||
/>
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
import React, { useState } from "react";
|
||||
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, { useState } from 'react';
|
||||
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 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 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 completeAccountInformationSignupInvite from "./api/auth/CompleteAccountInformationSignupInvite";
|
||||
import verifySignupInvite from "./api/auth/VerifySignupInvite";
|
||||
import completeAccountInformationSignupInvite from './api/auth/CompleteAccountInformationSignupInvite';
|
||||
import verifySignupInvite from './api/auth/VerifySignupInvite';
|
||||
|
||||
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();
|
||||
const queryString = require("query-string");
|
||||
const queryString = require('query-string');
|
||||
|
||||
export default function SignupInvite() {
|
||||
const [password, setPassword] = useState("");
|
||||
const [firstName, setFirstName] = useState("");
|
||||
const [lastName, setLastName] = useState("");
|
||||
const [password, setPassword] = useState('');
|
||||
const [firstName, setFirstName] = useState('');
|
||||
const [lastName, setLastName] = useState('');
|
||||
const [firstNameError, setFirstNameError] = useState(false);
|
||||
const [lastNameError, setLastNameError] = useState(false);
|
||||
const [passwordErrorLength, setPasswordErrorLength] = useState(false);
|
||||
const [passwordErrorNumber, setPasswordErrorNumber] = useState(false);
|
||||
const [passwordErrorLowerCase, setPasswordErrorLowerCase] = useState(false);
|
||||
const router = useRouter();
|
||||
const parsedUrl = queryString.parse(router.asPath.split("?")[1]);
|
||||
const parsedUrl = queryString.parse(router.asPath.split('?')[1]);
|
||||
const [email, setEmail] = useState(parsedUrl.to);
|
||||
const token = parsedUrl.token;
|
||||
const [errorLogin, setErrorLogin] = useState(false);
|
||||
@@ -74,21 +74,22 @@ export default function SignupInvite() {
|
||||
const PRIVATE_KEY = nacl.util.encodeBase64(secretKeyUint8Array);
|
||||
const PUBLIC_KEY = nacl.util.encodeBase64(publicKeyUint8Array);
|
||||
|
||||
const { ciphertext, iv, tag } = Aes256Gcm.encrypt(
|
||||
PRIVATE_KEY,
|
||||
password
|
||||
const { ciphertext, iv, tag } = Aes256Gcm.encrypt({
|
||||
text: PRIVATE_KEY,
|
||||
secret: password
|
||||
.slice(0, 32)
|
||||
.padStart(
|
||||
32 + (password.slice(0, 32).length - new Blob([password]).size),
|
||||
"0"
|
||||
'0'
|
||||
)
|
||||
);
|
||||
localStorage.setItem("PRIVATE_KEY", PRIVATE_KEY);
|
||||
});
|
||||
|
||||
localStorage.setItem('PRIVATE_KEY', PRIVATE_KEY);
|
||||
|
||||
client.init(
|
||||
{
|
||||
username: email,
|
||||
password: password,
|
||||
password: password
|
||||
},
|
||||
async () => {
|
||||
client.createVerifier(async (err, result) => {
|
||||
@@ -102,17 +103,17 @@ export default function SignupInvite() {
|
||||
tag,
|
||||
salt: result.salt,
|
||||
verifier: result.verifier,
|
||||
token: verificationToken,
|
||||
token: verificationToken
|
||||
});
|
||||
|
||||
// if everything works, go the main dashboard page.
|
||||
if (!errorCheck && response.status == "200") {
|
||||
if (!errorCheck && 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(
|
||||
@@ -126,7 +127,7 @@ export default function SignupInvite() {
|
||||
setStep(3);
|
||||
} catch (error) {
|
||||
setIsLoading(false);
|
||||
console.log("Error", error);
|
||||
console.log('Error', error);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -155,14 +156,14 @@ export default function SignupInvite() {
|
||||
onButtonPressed={async () => {
|
||||
const response = await verifySignupInvite({
|
||||
email,
|
||||
code: token,
|
||||
code: token
|
||||
});
|
||||
if (response.status == 200) {
|
||||
setVerificationToken((await response.json()).token);
|
||||
setStep(2);
|
||||
} else {
|
||||
console.log("ERROR", response);
|
||||
router.push("/requestnewinvite");
|
||||
console.log('ERROR', response);
|
||||
router.push('/requestnewinvite');
|
||||
}
|
||||
}}
|
||||
size="lg"
|
||||
@@ -211,7 +212,7 @@ export default function SignupInvite() {
|
||||
setPasswordErrorLength,
|
||||
setPasswordErrorNumber,
|
||||
setPasswordErrorLowerCase,
|
||||
currentErrorCheck: false,
|
||||
currentErrorCheck: false
|
||||
});
|
||||
}}
|
||||
type="password"
|
||||
@@ -244,7 +245,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
|
||||
@@ -264,7 +265,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
|
||||
@@ -284,7 +285,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
|
||||
@@ -335,11 +336,11 @@ export default function SignupInvite() {
|
||||
await issueBackupKey({
|
||||
email,
|
||||
password,
|
||||
personalName: firstName + " " + lastName,
|
||||
personalName: firstName + ' ' + lastName,
|
||||
setBackupKeyError,
|
||||
setBackupKeyIssued,
|
||||
setBackupKeyIssued
|
||||
});
|
||||
router.push("/dashboard/");
|
||||
router.push('/dashboard/');
|
||||
}}
|
||||
size="lg"
|
||||
/>
|
||||
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user