chore(frontend): fixed all eslint errors

This commit is contained in:
akhilmhdh
2023-01-17 21:06:14 +05:30
parent 9f82e2d836
commit cf7834bfc3
184 changed files with 6255 additions and 6117 deletions
@@ -1,32 +1,27 @@
import token from '~/pages/api/auth/Token';
import token from '@app/pages/api/auth/Token';
export default class SecurityClient {
static #token = '';
constructor() {}
static setToken(token: string) {
this.#token = token;
static setToken(tokenStr: string) {
this.#token = tokenStr;
}
static async fetchCall(
resource: RequestInfo,
options?: RequestInit | undefined
) {
static async fetchCall(resource: RequestInfo, options?: RequestInit | undefined) {
const req = new Request(resource, options);
if (this.#token == '') {
if (this.#token === '') {
try {
// TODO: This should be moved to a context to do it only once when app loads
// this try catch saves route guard from a stuck state
this.setToken(await token());
} catch (error) {
console.error("Unauthorized access");
console.error('Unauthorized access');
}
}
if (this.#token) {
req.headers.set('Authorization', 'Bearer ' + this.#token);
req.headers.set('Authorization', `Bearer ${this.#token}`);
}
return fetch(req);
+101 -91
View File
@@ -1,13 +1,16 @@
import { SecretDataProps } from 'public/data/frequentInterfaces';
/* eslint-disable prefer-destructuring */
import crypto from 'crypto';
import Aes256Gcm from '~/components/utilities/cryptography/aes-256-gcm';
import login1 from '~/pages/api/auth/Login1';
import login2 from '~/pages/api/auth/Login2';
import addSecrets from '~/pages/api/files/AddSecrets';
import getOrganizations from '~/pages/api/organization/getOrgs';
import getOrganizationUserProjects from '~/pages/api/organization/GetOrgUserProjects';
import getUser from '~/pages/api/user/getUser';
import uploadKeys from '~/pages/api/workspace/uploadKeys';
import Aes256Gcm from '@app/components/utilities/cryptography/aes-256-gcm';
import login1 from '@app/pages/api/auth/Login1';
import login2 from '@app/pages/api/auth/Login2';
import addSecrets from '@app/pages/api/files/AddSecrets';
import getOrganizations from '@app/pages/api/organization/getOrgs';
import getOrganizationUserProjects from '@app/pages/api/organization/GetOrgUserProjects';
import getUser from '@app/pages/api/user/getUser';
import uploadKeys from '@app/pages/api/workspace/uploadKeys';
import jsrp from 'jsrp';
import { SecretDataProps } from 'public/data/frequentInterfaces';
import { encryptAssymmetric } from './cryptography/crypto';
import encryptSecrets from './secrets/encryptSecrets';
@@ -15,11 +18,7 @@ import Telemetry from './telemetry/Telemetry';
import { saveTokenToLocalStorage } from './saveTokenToLocalStorage';
import SecurityClient from './SecurityClient';
const crypto = require("crypto");
const nacl = require('tweetnacl');
nacl.util = require('tweetnacl-util');
const jsrp = require('jsrp');
// eslint-disable-next-line new-cap
const client = new jsrp.client();
/**
@@ -46,7 +45,7 @@ const attemptLogin = async (
client.init(
{
username: email,
password: password
password
},
async () => {
const clientPublicKey = client.getPublicKey();
@@ -59,8 +58,10 @@ const attemptLogin = async (
const clientProof = client.getProof(); // called M1
// if everything works, go the main dashboard page.
const { token, publicKey, encryptedPrivateKey, iv, tag } =
await login2(email, clientProof);
const { token, publicKey, encryptedPrivateKey, iv, tag } = await login2(
email,
clientProof
);
SecurityClient.setToken(token);
@@ -70,10 +71,7 @@ const attemptLogin = async (
tag,
secret: password
.slice(0, 32)
.padStart(
32 + (password.slice(0, 32).length - new Blob([password]).size),
'0'
)
.padStart(32 + (password.slice(0, 32).length - new Blob([password]).size), '0')
});
saveTokenToLocalStorage({
@@ -83,9 +81,9 @@ const attemptLogin = async (
tag,
privateKey
});
const userOrgs = await getOrganizations();
const userOrgsData = userOrgs.map((org: { _id: string; }) => org._id);
const userOrgsData = userOrgs.map((org: { _id: string }) => org._id);
let orgToLogin;
if (userOrgsData.includes(localStorage.getItem('orgData.id'))) {
@@ -99,11 +97,9 @@ const attemptLogin = async (
orgId: orgToLogin
});
orgUserProjects = orgUserProjects?.map((project: { _id: string; }) => project._id);
orgUserProjects = orgUserProjects?.map((project: { _id: string }) => project._id);
let projectToLogin;
if (
orgUserProjects.includes(localStorage.getItem('projectData.id'))
) {
if (orgUserProjects.includes(localStorage.getItem('projectData.id'))) {
projectToLogin = localStorage.getItem('projectData.id');
} else {
try {
@@ -113,90 +109,104 @@ const attemptLogin = async (
console.log('ERROR: User likely has no projects. ', error);
}
}
if (email) {
telemetry.identify(email);
telemetry.capture('User Logged In');
}
if (isSignUp) {
const randomBytes = crypto.randomBytes(16).toString("hex");
const PRIVATE_KEY = String(localStorage.getItem("PRIVATE_KEY"));
const randomBytes = crypto.randomBytes(16).toString('hex');
const PRIVATE_KEY = String(localStorage.getItem('PRIVATE_KEY'));
const myUser = await getUser();
const { ciphertext, nonce } = encryptAssymmetric({
plaintext: randomBytes,
publicKey: myUser.publicKey,
privateKey: PRIVATE_KEY,
privateKey: PRIVATE_KEY
}) as { ciphertext: string; nonce: string };
await uploadKeys(
projectToLogin,
myUser._id,
ciphertext,
nonce
);
await uploadKeys(projectToLogin, myUser._id, ciphertext, nonce);
const secretsToBeAdded: SecretDataProps[] = [{
pos: 0,
key: "DATABASE_URL",
value: "mongodb+srv://${DB_USERNAME}:${DB_PASSWORD}@mongodb.net",
valueOverride: undefined,
comment: "This is an example of secret referencing.",
id: ''
}, {
pos: 1,
key: "DB_USERNAME",
value: "OVERRIDE_THIS",
valueOverride: undefined,
comment: "This is an example of secret overriding. Your team can have a shared value of a secret, while you can override it to whatever value you need",
id: ''
}, {
pos: 2,
key: "DB_PASSWORD",
value: "OVERRIDE_THIS",
valueOverride: undefined,
comment: "This is an example of secret overriding. Your team can have a shared value of a secret, while you can override it to whatever value you need",
id: ''
}, {
pos: 3,
key: "DB_USERNAME",
value: "user1234",
valueOverride: "user1234",
comment: "",
id: ''
}, {
pos: 4,
key: "DB_PASSWORD",
value: "example_password",
valueOverride: "example_password",
comment: "",
id: ''
}, {
pos: 5,
key: "TWILIO_AUTH_TOKEN",
value: "example_twillio_token",
valueOverride: undefined,
comment: "",
id: ''
}, {
pos: 6,
key: "WEBSITE_URL",
value: "http://localhost:3000",
valueOverride: undefined,
comment: "",
id: ''
}]
const secrets = await encryptSecrets({ secretsToEncrypt: secretsToBeAdded, workspaceId: String(localStorage.getItem('projectData.id')), env: 'dev' })
await addSecrets({ secrets: secrets ?? [], env: "dev", workspaceId: String(localStorage.getItem('projectData.id')) });
const secretsToBeAdded: SecretDataProps[] = [
{
pos: 0,
key: 'DATABASE_URL',
// eslint-disable-next-line no-template-curly-in-string
value: 'mongodb+srv://${DB_USERNAME}:${DB_PASSWORD}@mongodb.net',
valueOverride: undefined,
comment: 'This is an example of secret referencing.',
id: ''
},
{
pos: 1,
key: 'DB_USERNAME',
value: 'OVERRIDE_THIS',
valueOverride: undefined,
comment:
'This is an example of secret overriding. Your team can have a shared value of a secret, while you can override it to whatever value you need',
id: ''
},
{
pos: 2,
key: 'DB_PASSWORD',
value: 'OVERRIDE_THIS',
valueOverride: undefined,
comment:
'This is an example of secret overriding. Your team can have a shared value of a secret, while you can override it to whatever value you need',
id: ''
},
{
pos: 3,
key: 'DB_USERNAME',
value: 'user1234',
valueOverride: 'user1234',
comment: '',
id: ''
},
{
pos: 4,
key: 'DB_PASSWORD',
value: 'example_password',
valueOverride: 'example_password',
comment: '',
id: ''
},
{
pos: 5,
key: 'TWILIO_AUTH_TOKEN',
value: 'example_twillio_token',
valueOverride: undefined,
comment: '',
id: ''
},
{
pos: 6,
key: 'WEBSITE_URL',
value: 'http://localhost:3000',
valueOverride: undefined,
comment: '',
id: ''
}
];
const secrets = await encryptSecrets({
secretsToEncrypt: secretsToBeAdded,
workspaceId: String(localStorage.getItem('projectData.id')),
env: 'dev'
});
await addSecrets({
secrets: secrets ?? [],
env: 'dev',
workspaceId: String(localStorage.getItem('projectData.id'))
});
}
if (isLogin) {
router.push('/dashboard/' + localStorage.getItem('projectData.id'));
router.push(`/dashboard/${localStorage.getItem('projectData.id')}`);
}
} catch (error) {
console.log(error)
console.log(error);
setErrorLogin(true);
console.log('Login response not available');
}
@@ -1,5 +1,5 @@
import getOrganizationUsers from '~/pages/api/organization/GetOrgUsers';
import checkUserAction from '~/pages/api/userActions/checkUserAction';
import getOrganizationUsers from '@app/pages/api/organization/GetOrgUsers';
import checkUserAction from '@app/pages/api/userActions/checkUserAction';
interface OnboardingCheckProps {
setTotalOnboardingActionsDone?: (value: number) => void;
@@ -26,46 +26,43 @@ const onboardingCheck = async ({
action: 'slack_cta_clicked'
});
if (userActionSlack) {
countActions = countActions + 1;
countActions += 1;
}
setHasUserClickedSlack &&
setHasUserClickedSlack(userActionSlack ? true : false);
if (setHasUserClickedSlack) setHasUserClickedSlack(!!userActionSlack);
const userActionSecrets = await checkUserAction({
action: 'first_time_secrets_pushed'
});
if (userActionSecrets) {
countActions = countActions + 1;
countActions += 1;
}
setHasUserPushedSecrets &&
setHasUserPushedSecrets(userActionSecrets ? true : false);
if (setHasUserPushedSecrets) setHasUserPushedSecrets(!!userActionSecrets);
const userActionIntro = await checkUserAction({
action: 'intro_cta_clicked'
});
if (userActionIntro) {
countActions = countActions + 1;
countActions += 1;
}
setHasUserClickedIntro &&
setHasUserClickedIntro(userActionIntro ? true : false);
if (setHasUserClickedIntro) setHasUserClickedIntro(!!userActionIntro);
const userActionStar = await checkUserAction({
action: 'star_cta_clicked'
});
if (userActionStar) {
countActions = countActions + 1;
countActions += 1;
}
setHasUserStarred && setHasUserStarred(userActionStar ? true : false);
if (setHasUserStarred) setHasUserStarred(!!userActionStar);
const orgId = localStorage.getItem('orgData.id');
const orgUsers = await getOrganizationUsers({
orgId: orgId ? orgId : ''
orgId: orgId || ''
});
if (orgUsers.length > 1) {
countActions = countActions + 1;
countActions += 1;
}
setUsersInOrg && setUsersInOrg(orgUsers.length > 1);
setTotalOnboardingActionsDone && setTotalOnboardingActionsDone(countActions);
if (setUsersInOrg) setUsersInOrg(orgUsers.length > 1);
if (setTotalOnboardingActionsDone) setTotalOnboardingActionsDone(countActions);
};
export default onboardingCheck;
@@ -1,3 +1,4 @@
/* eslint-disable no-param-reassign */
interface PasswordCheckProps {
password: string;
errorCheck: boolean;
@@ -14,7 +15,7 @@ const passwordCheck = ({
setPasswordErrorLength,
setPasswordErrorNumber,
setPasswordErrorLowerCase,
errorCheck,
errorCheck
}: PasswordCheckProps) => {
if (!password || password.length < 14) {
setPasswordErrorLength(true);
@@ -32,7 +32,6 @@ class Aes256Gcm {
/**
* No need to run the constructor. The class only has static methods.
*/
constructor() {}
/**
* Encrypts text with AES 256 GCM.
@@ -65,11 +64,7 @@ class Aes256Gcm {
* @returns {string}
*/
static decrypt({ ciphertext, iv, tag, secret }: DecryptProps): string {
const decipher = crypto.createDecipheriv(
ALGORITHM,
secret,
Buffer.from(iv, 'base64')
);
const decipher = crypto.createDecipheriv(ALGORITHM, secret, Buffer.from(iv, 'base64'));
decipher.setAuthTag(Buffer.from(tag, 'base64'));
let cleartext = decipher.update(ciphertext, 'base64', 'utf8');
@@ -1,8 +1,8 @@
/* eslint-disable new-cap */
import changePassword2 from '@app/pages/api/auth/ChangePassword2';
import SRP1 from '@app/pages/api/auth/SRP1';
import jsrp from 'jsrp';
import changePassword2 from '~/pages/api/auth/ChangePassword2';
import SRP1 from '~/pages/api/auth/SRP1';
import Aes256Gcm from './aes-256-gcm';
const clientOldPassword = new jsrp.client();
@@ -33,15 +33,16 @@ const changePassword = async (
clientOldPassword.init(
{
username: email,
password: currentPassword,
password: currentPassword
},
async () => {
const clientPublicKey = clientOldPassword.getPublicKey();
let serverPublicKey, salt;
let serverPublicKey;
let salt;
try {
const res = await SRP1({
clientPublicKey: clientPublicKey,
clientPublicKey
});
serverPublicKey = res.serverPublicKey;
salt = res.salt;
@@ -57,7 +58,7 @@ const changePassword = async (
clientNewPassword.init(
{
username: email,
password: newPassword,
password: newPassword
},
async () => {
clientNewPassword.createVerifier(async (err, result) => {
@@ -67,11 +68,9 @@ const changePassword = async (
secret: newPassword
.slice(0, 32)
.padStart(
32 +
(newPassword.slice(0, 32).length -
new Blob([newPassword]).size),
32 + (newPassword.slice(0, 32).length - new Blob([newPassword]).size),
'0'
),
)
});
if (ciphertext) {
@@ -87,18 +86,18 @@ const changePassword = async (
tag,
salt: result.salt,
verifier: result.verifier,
clientProof,
clientProof
});
if (res && res.status == 400) {
if (res && res.status === 400) {
setCurrentPasswordError(true);
} else if (res && res.status == 200) {
} else if (res && res.status === 200) {
setPasswordChanged(true);
setCurrentPassword('');
setNewPassword('');
}
} catch (err) {
} catch (error) {
setCurrentPasswordError(true);
console.log(err);
console.log(error);
}
}
});
@@ -1,8 +1,9 @@
const nacl = require('tweetnacl');
nacl.util = require('tweetnacl-util');
import aes from './aes-256-gcm';
type encryptAsymmetricProps = {
const nacl = require('tweetnacl');
nacl.util = require('tweetnacl-util');
type EncryptAsymmetricProps = {
plaintext: string;
publicKey: string;
privateKey: string;
@@ -22,8 +23,8 @@ type encryptAsymmetricProps = {
const encryptAssymmetric = ({
plaintext,
publicKey,
privateKey,
}: encryptAsymmetricProps): {
privateKey
}: EncryptAsymmetricProps): {
ciphertext: string;
nonce: string;
} => {
@@ -37,11 +38,11 @@ const encryptAssymmetric = ({
return {
ciphertext: nacl.util.encodeBase64(ciphertext),
nonce: nacl.util.encodeBase64(nonce),
nonce: nacl.util.encodeBase64(nonce)
};
};
type decryptAsymmetricProps = {
type DecryptAsymmetricProps = {
ciphertext: string;
nonce: string;
publicKey: string;
@@ -61,8 +62,8 @@ const decryptAssymmetric = ({
ciphertext,
nonce,
publicKey,
privateKey,
}: decryptAsymmetricProps): string => {
privateKey
}: DecryptAsymmetricProps): string => {
const plaintext = nacl.box.open(
nacl.util.decodeBase64(ciphertext),
nacl.util.decodeBase64(nonce),
@@ -73,24 +74,23 @@ const decryptAssymmetric = ({
return nacl.util.encodeUTF8(plaintext);
};
type encryptSymmetricProps = {
type EncryptSymmetricProps = {
plaintext: string;
key: string;
};
type encryptSymmetricReturn = {
ciphertext:string;
iv:string;
tag:string;
type EncryptSymmetricReturn = {
ciphertext: string;
iv: string;
tag: string;
};
/**
* Return symmetrically encrypted [plaintext] using [key].
*/
const encryptSymmetric = ({
plaintext,
key,
}: encryptSymmetricProps): encryptSymmetricReturn => {
let ciphertext, iv, tag;
const encryptSymmetric = ({ plaintext, key }: EncryptSymmetricProps): EncryptSymmetricReturn => {
let ciphertext;
let iv;
let tag;
try {
const obj = aes.encrypt({ text: plaintext, secret: key });
ciphertext = obj.ciphertext;
@@ -105,11 +105,11 @@ const encryptSymmetric = ({
return {
ciphertext,
iv,
tag,
tag
};
};
type decryptSymmetricProps = {
type DecryptSymmetricProps = {
ciphertext: string;
iv: string;
tag: string;
@@ -126,12 +126,7 @@ type decryptSymmetricProps = {
* @param {String} obj.key - 32-byte hex key
*
*/
const decryptSymmetric = ({
ciphertext,
iv,
tag,
key,
}: decryptSymmetricProps): string => {
const decryptSymmetric = ({ ciphertext, iv, tag, key }: DecryptSymmetricProps): string => {
let plaintext;
try {
plaintext = aes.decrypt({ ciphertext, iv, tag, secret: key });
@@ -143,9 +138,4 @@ const decryptSymmetric = ({
return plaintext;
};
export {
decryptAssymmetric,
decryptSymmetric,
encryptAssymmetric,
encryptSymmetric,
};
export { decryptAssymmetric, decryptSymmetric, encryptAssymmetric, encryptSymmetric };
@@ -1,15 +1,15 @@
import issueBackupPrivateKey from '~/pages/api/auth/IssueBackupPrivateKey';
import SRP1 from '~/pages/api/auth/SRP1';
/* eslint-disable new-cap */
import crypto from 'crypto';
import issueBackupPrivateKey from '@app/pages/api/auth/IssueBackupPrivateKey';
import SRP1 from '@app/pages/api/auth/SRP1';
import jsrp from 'jsrp';
import generateBackupPDF from '../generateBackupPDF';
import Aes256Gcm from './aes-256-gcm';
const nacl = require('tweetnacl');
nacl.util = require('tweetnacl-util');
const jsrp = require('jsrp');
const clientPassword = new jsrp.client();
const clientKey = new jsrp.client();
const crypto = require('crypto');
interface BackupKeyProps {
email: string;
@@ -42,15 +42,16 @@ const issueBackupKey = async ({
clientPassword.init(
{
username: email,
password: password
password
},
async () => {
const clientPublicKey = clientPassword.getPublicKey();
let serverPublicKey, salt;
let serverPublicKey;
let salt;
try {
const res = await SRP1({
clientPublicKey: clientPublicKey
clientPublicKey
});
serverPublicKey = res.serverPublicKey;
salt = res.salt;
@@ -87,9 +88,9 @@ const issueBackupKey = async ({
clientProof
});
if (res?.status == 400) {
if (res?.status === 400) {
setBackupKeyError(true);
} else if (res?.status == 200) {
} else if (res?.status === 200) {
generateBackupPDF({
personalName,
personalEmail: email,
File diff suppressed because one or more lines are too long
@@ -29,6 +29,7 @@ export function parseDotEnv(src: ArrayBuffer) {
let match;
let item: [string, string, string[]] | [] = [];
// eslint-disable-next-line no-cond-assign
while ((match = LINE.exec(line)) !== null) {
const key = match[1];
@@ -58,8 +59,8 @@ export function parseDotEnv(src: ArrayBuffer) {
})
.filter((line) => line.length > 1)
.forEach((line) => {
const [key, value, comments] = line;
object[key as string] = { value, comments };
const [key, value, cmnts] = line;
object[key as string] = { value, comments: cmnts };
});
return object;
+3 -15
View File
@@ -3,23 +3,11 @@
* @returns
*/
const guidGenerator = () => {
const S4 = function () {
const S4 = () => {
// eslint-disable-next-line no-bitwise
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
};
return (
S4() +
S4() +
'-' +
S4() +
'-' +
S4() +
'-' +
S4() +
'-' +
S4() +
S4() +
S4()
);
return `${S4() + S4()}-${S4()}-${S4()}-${S4()}-${S4()}${S4()}${S4()}`;
};
export default guidGenerator;
@@ -22,7 +22,7 @@ export const saveTokenToLocalStorage = ({
} catch (err) {
if (err instanceof Error) {
throw new Error(
"Unable to send the tokens in local storage:" + err.message
`Unable to send the tokens in local storage:${ err.message}`
);
}
}
@@ -1,26 +1,32 @@
import { SecretDataProps } from "public/data/frequentInterfaces";
import { SecretDataProps } from 'public/data/frequentInterfaces';
/**
* This function downloads the secrets as a .env file
* @param {object} obj
* @param {object} obj
* @param {SecretDataProps[]} obj.data - secrets that we want to check for overrides
* @returns
* @returns
*/
const checkOverrides = async ({ data }: { data: SecretDataProps[]; }) => {
let secrets : SecretDataProps[] = data!.map((secret) => Object.create(secret));
const overridenSecrets = data!.filter(
(secret) => (secret.valueOverride == undefined || secret?.value != secret?.valueOverride) ? 'shared' : 'personal'
const checkOverrides = async ({ data }: { data: SecretDataProps[] }) => {
let secrets: SecretDataProps[] = data!.map((secret) => Object.create(secret));
const overridenSecrets = data!.filter((secret) =>
secret.valueOverride === undefined || secret?.value !== secret?.valueOverride
? 'shared'
: 'personal'
);
if (overridenSecrets.length) {
overridenSecrets.forEach((secret) => {
const index = secrets!.findIndex(
(_secret) => _secret.key === secret.key && (secret.valueOverride == undefined || secret?.value != secret?.valueOverride)
(_secret) =>
_secret.key === secret.key &&
(secret.valueOverride === undefined || secret?.value !== secret?.valueOverride)
);
secrets![index].value = secret.value;
});
secrets = secrets!.filter((secret) => (secret.valueOverride == undefined || secret?.value != secret?.valueOverride));
secrets = secrets!.filter(
(secret) => secret.valueOverride === undefined || secret?.value !== secret?.valueOverride
);
}
return secrets;
}
};
export default checkOverrides;
@@ -1,16 +1,14 @@
import { envMapping } from "public/data/frequentConstants";
import { SecretDataProps } from "public/data/frequentInterfaces";
import { SecretDataProps } from 'public/data/frequentInterfaces';
import checkOverrides from './checkOverrides';
/**
* This function downloads the secrets as a .env file
* @param {object} obj
* @param {object} obj
* @param {SecretDataProps[]} obj.data - secrets that we want to download
* @param {string} obj.env - the environment which we're downloading (used for naming the file)
*/
const downloadDotEnv = async ({ data, env }: { data: SecretDataProps[]; env: string; }) => {
const downloadDotEnv = async ({ data, env }: { data: SecretDataProps[]; env: string }) => {
if (!data) return;
const secrets = await checkOverrides({ data });
@@ -19,21 +17,21 @@ const downloadDotEnv = async ({ data, env }: { data: SecretDataProps[]; env: str
(item: SecretDataProps) =>
`${
item.comment
? item.comment
? `${item.comment
.split('\n')
.map((comment) => '# '.concat(comment))
.join('\n') + '\n'
.join('\n')}\n`
: ''
}` + [item.key, item.value].join('=')
}${[item.key, item.value].join('=')}`
)
.join('\n');
const blob = new Blob([file]);
const fileDownloadUrl = URL.createObjectURL(blob);
const alink = document.createElement('a');
alink.href = fileDownloadUrl;
alink.download = env + '.env';
alink.click();
}
const blob = new Blob([file]);
const fileDownloadUrl = URL.createObjectURL(blob);
const alink = document.createElement('a');
alink.href = fileDownloadUrl;
alink.download = `${env}.env`;
alink.click();
};
export default downloadDotEnv;
@@ -1,20 +1,20 @@
// import YAML from 'yaml';
// import { YAMLSeq } from 'yaml/types';
import { SecretDataProps } from "public/data/frequentInterfaces";
import { SecretDataProps } from 'public/data/frequentInterfaces';
// import { envMapping } from "../../../public/data/frequentConstants";
// import checkOverrides from './checkOverrides';
/**
* This function downloads the secrets as a .yml file
* @param {object} obj
* @param {object} obj
* @param {SecretDataProps[]} obj.data - secrets that we want to download
* @param {string} obj.env - used for naming the file
* @returns
* @returns
*/
const downloadYaml = async ({ data, env }: { data: SecretDataProps[]; env: string; }) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const downloadYaml = async ({ data, env }: { data: SecretDataProps[]; env: string }) => {
// if (!data) return;
// const doc = new YAML.Document();
// doc.contents = new YAMLSeq();
@@ -27,20 +27,17 @@ const downloadYaml = async ({ data, env }: { data: SecretDataProps[]; env: strin
// .join('\n');
// doc.add(pair);
// });
// const file = doc
// .toString()
// .split('\n')
// .map((line) => (line.startsWith('-') ? line.replace('- ', '') : line))
// .join('\n');
// const blob = new Blob([file]);
// const fileDownloadUrl = URL.createObjectURL(blob);
// const alink = document.createElement('a');
// alink.href = fileDownloadUrl;
// alink.download = envMapping[env] + '.yml';
// alink.click();
return;
}
};
export default downloadYaml;
@@ -1,15 +1,9 @@
import { SecretDataProps } from "public/data/frequentInterfaces";
import crypto from 'crypto';
import getLatestFileKey from "~/pages/api/workspace/getLatestFileKey";
const crypto = require("crypto");
const {
decryptAssymmetric,
encryptSymmetric,
} = require("../cryptography/crypto");
const nacl = require("tweetnacl");
nacl.util = require("tweetnacl-util");
import getLatestFileKey from '@app/pages/api/workspace/getLatestFileKey';
import { SecretDataProps } from 'public/data/frequentInterfaces';
import { decryptAssymmetric, encryptSymmetric } from '../cryptography/crypto';
interface EncryptedSecretProps {
id: string;
@@ -24,22 +18,30 @@ interface EncryptedSecretProps {
secretValueCiphertext: string;
secretValueIV: string;
secretValueTag: string;
type: "personal" | "shared";
type: 'personal' | 'shared';
}
/**
* Encypt secrets before pushing the to the DB
* @param {object} obj
* @param {object} obj
* @param {object} obj.secretsToEncrypt - secrets that we want to encrypt
* @param {object} obj.workspaceId - the id of a project in which we are encrypting secrets
* @returns
* @returns
*/
const encryptSecrets = async ({ secretsToEncrypt, workspaceId, env }: { secretsToEncrypt: SecretDataProps[]; workspaceId: string; env: string; }) => {
const encryptSecrets = async ({
secretsToEncrypt,
workspaceId,
env
}: {
secretsToEncrypt: SecretDataProps[];
workspaceId: string;
env: string;
}) => {
let secrets;
try {
const sharedKey = await getLatestFileKey({ workspaceId });
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY");
const PRIVATE_KEY = localStorage.getItem('PRIVATE_KEY') as string;
let randomBytes: string;
if (Object.keys(sharedKey).length > 0) {
@@ -48,42 +50,42 @@ const encryptSecrets = async ({ secretsToEncrypt, workspaceId, env }: { secretsT
ciphertext: sharedKey.latestKey.encryptedKey,
nonce: sharedKey.latestKey.nonce,
publicKey: sharedKey.latestKey.sender.publicKey,
privateKey: PRIVATE_KEY,
privateKey: PRIVATE_KEY
});
} else {
// case: a (shared) key does not exist for the workspace
randomBytes = crypto.randomBytes(16).toString("hex");
randomBytes = crypto.randomBytes(16).toString('hex');
}
secrets = secretsToEncrypt.map((secret) => {
// encrypt key
const {
ciphertext: secretKeyCiphertext,
iv: secretKeyIV,
tag: secretKeyTag,
tag: secretKeyTag
} = encryptSymmetric({
plaintext: secret.key,
key: randomBytes,
key: randomBytes
});
// encrypt value
const {
ciphertext: secretValueCiphertext,
iv: secretValueIV,
tag: secretValueTag,
tag: secretValueTag
} = encryptSymmetric({
plaintext: secret.value,
key: randomBytes,
key: randomBytes
});
// encrypt comment
const {
ciphertext: secretCommentCiphertext,
iv: secretCommentIV,
tag: secretCommentTag,
tag: secretCommentTag
} = encryptSymmetric({
plaintext: secret.comment ?? '',
key: randomBytes,
key: randomBytes
});
const result: EncryptedSecretProps = {
@@ -99,17 +101,19 @@ const encryptSecrets = async ({ secretsToEncrypt, workspaceId, env }: { secretsT
secretCommentCiphertext,
secretCommentIV,
secretCommentTag,
type: (secret.valueOverride == undefined || secret?.value != secret?.valueOverride) ? 'shared' : 'personal',
type:
secret.valueOverride === undefined || secret?.value !== secret?.valueOverride
? 'shared'
: 'personal'
};
return result;
});
} catch (error) {
console.log("Error while encrypting secrets");
console.log('Error while encrypting secrets');
}
return secrets;
}
};
export default encryptSecrets;
@@ -1,12 +1,7 @@
import getSecrets from '~/pages/api/files/GetSecrets';
import getLatestFileKey from '~/pages/api/workspace/getLatestFileKey';
import getSecrets from '@app/pages/api/files/GetSecrets';
import getLatestFileKey from '@app/pages/api/workspace/getLatestFileKey';
const {
decryptAssymmetric,
decryptSymmetric
} = require('../cryptography/crypto');
const nacl = require('tweetnacl');
nacl.util = require('tweetnacl-util');
import { decryptAssymmetric, decryptSymmetric } from '../cryptography/crypto';
interface EncryptedSecretProps {
_id: string;
@@ -21,14 +16,14 @@ interface EncryptedSecretProps {
secretValueCiphertext: string;
secretValueIV: string;
secretValueTag: string;
type: "personal" | "shared";
type: 'personal' | 'shared';
}
interface SecretProps {
key: string;
value: string;
type: 'personal' | 'shared';
comment: string;
interface SecretProps {
key: string;
value: string;
type: 'personal' | 'shared';
comment: string;
id: string;
}
@@ -61,11 +56,11 @@ const getSecretsForProject = async ({
console.log('ERROR: Not able to access the latest version of secrets');
}
const latestKey = await getLatestFileKey({ workspaceId })
const latestKey = await getLatestFileKey({ workspaceId });
// This is called isKeyAvailable but what it really means is if a person is able to create new key pairs
setIsKeyAvailable(!latestKey ? encryptedSecrets.length == 0 : true);
setIsKeyAvailable(!latestKey ? encryptedSecrets.length === 0 : true);
const PRIVATE_KEY = localStorage.getItem('PRIVATE_KEY');
const PRIVATE_KEY = localStorage.getItem('PRIVATE_KEY') as string;
const tempDecryptedSecrets: SecretProps[] = [];
if (latestKey) {
@@ -78,7 +73,7 @@ const getSecretsForProject = async ({
});
// decrypt secret keys, values, and comments
encryptedSecrets.map((secret: EncryptedSecretProps) => {
encryptedSecrets.forEach((secret: EncryptedSecretProps) => {
const plainTextKey = decryptSymmetric({
ciphertext: secret.secretKeyCiphertext,
iv: secret.secretKeyIV,
@@ -102,7 +97,7 @@ const getSecretsForProject = async ({
key
});
} else {
plainTextComment = "";
plainTextComment = '';
}
tempDecryptedSecrets.push({
@@ -115,20 +110,26 @@ const getSecretsForProject = async ({
});
}
const secretKeys = [...new Set(tempDecryptedSecrets.map(secret => secret.key))];
const secretKeys = [...new Set(tempDecryptedSecrets.map((secret) => secret.key))];
const result = secretKeys.map((key, index) => {
return {
id: tempDecryptedSecrets.filter(secret => secret.key == key && secret.type == 'shared')[0]?.id,
idOverride: tempDecryptedSecrets.filter(secret => secret.key == key && secret.type == 'personal')[0]?.id,
pos: index,
key: key,
value: tempDecryptedSecrets.filter(secret => secret.key == key && secret.type == 'shared')[0]?.value,
valueOverride: tempDecryptedSecrets.filter(secret => secret.key == key && secret.type == 'personal')[0]?.value,
comment: tempDecryptedSecrets.filter(secret => secret.key == key && secret.type == 'shared')[0]?.comment,
}
});
const result = secretKeys.map((key, index) => ({
id: tempDecryptedSecrets.filter((secret) => secret.key === key && secret.type === 'shared')[0]
?.id,
idOverride: tempDecryptedSecrets.filter(
(secret) => secret.key === key && secret.type === 'personal'
)[0]?.id,
pos: index,
key,
value: tempDecryptedSecrets.filter(
(secret) => secret.key === key && secret.type === 'shared'
)[0]?.value,
valueOverride: tempDecryptedSecrets.filter(
(secret) => secret.key === key && secret.type === 'personal'
)[0]?.value,
comment: tempDecryptedSecrets.filter(
(secret) => secret.key === key && secret.type === 'shared'
)[0]?.comment
}));
setData(result);
return result;
@@ -1,7 +1,7 @@
/* eslint-disable */
import { PostHog } from 'posthog-js';
import { initPostHog } from '~/components/analytics/posthog';
import { ENV } from '~/components/utilities/config';
import { initPostHog } from '@app/components/analytics/posthog';
import { ENV } from '@app/components/utilities/config';
declare let TELEMETRY_CAPTURING_ENABLED: any;
@@ -13,7 +13,7 @@ class Capturer {
}
capture(item: string) {
if (ENV == 'production' && TELEMETRY_CAPTURING_ENABLED) {
if (ENV === 'production' && TELEMETRY_CAPTURING_ENABLED) {
try {
this.api.capture(item);
} catch (error) {
@@ -23,7 +23,7 @@ class Capturer {
}
identify(id: string) {
if (ENV == 'production' && TELEMETRY_CAPTURING_ENABLED) {
if (ENV === 'production' && TELEMETRY_CAPTURING_ENABLED) {
try {
this.api.identify(id);
} catch (error) {