Fix merge conflicts frontend integrations

This commit is contained in:
Tuan Dang
2022-12-11 11:45:47 -05:00
110 changed files with 2084 additions and 1847 deletions
@@ -1,24 +0,0 @@
import token from "~/pages/api/auth/Token";
export default class SecurityClient {
static #token = "";
constructor() {}
static setToken(token) {
this.#token = token;
}
static async fetchCall(resource, options) {
let req = new Request(resource, options);
if (this.#token == "") {
this.setToken(await token());
}
if (this.#token) {
req.headers.set("Authorization", "Bearer " + this.#token);
return fetch(req);
}
}
}
@@ -0,0 +1,27 @@
import token from '~/pages/api/auth/Token';
export default class SecurityClient {
static #token = '';
constructor() {}
static setToken(token: string) {
this.#token = token;
}
static async fetchCall(
resource: RequestInfo,
options?: RequestInit | undefined
) {
const req = new Request(resource, options);
if (this.#token == '') {
this.setToken(await token());
}
if (this.#token) {
req.headers.set('Authorization', 'Bearer ' + this.#token);
return fetch(req);
}
}
}
+36 -36
View File
@@ -1,17 +1,17 @@
import Aes256Gcm from "~/components/utilities/cryptography/aes-256-gcm";
import login1 from "~/pages/api/auth/Login1";
import login2 from "~/pages/api/auth/Login2";
import getOrganizations from "~/pages/api/organization/getOrgs";
import getOrganizationUserProjects from "~/pages/api/organization/GetOrgUserProjects";
import Aes256Gcm from '~/components/utilities/cryptography/aes-256-gcm';
import login1 from '~/pages/api/auth/Login1';
import login2 from '~/pages/api/auth/Login2';
import getOrganizations from '~/pages/api/organization/getOrgs';
import getOrganizationUserProjects from '~/pages/api/organization/GetOrgUserProjects';
import pushKeys from "./secrets/pushKeys";
import { saveTokenToLocalStorage } from "./saveTokenToLocalStorage";
import SecurityClient from "./SecurityClient";
import Telemetry from "./telemetry/Telemetry";
import pushKeys from './secrets/pushKeys';
import Telemetry from './telemetry/Telemetry';
import { saveTokenToLocalStorage } from './saveTokenToLocalStorage';
import SecurityClient from './SecurityClient';
const nacl = require("tweetnacl");
nacl.util = require("tweetnacl-util");
const jsrp = require("jsrp");
const nacl = require('tweetnacl');
nacl.util = require('tweetnacl-util');
const jsrp = require('jsrp');
const client = new jsrp.client();
/**
@@ -37,7 +37,7 @@ const attemptLogin = async (
client.init(
{
username: email,
password: password,
password: password
},
async () => {
const clientPublicKey = client.getPublicKey();
@@ -62,7 +62,7 @@ const attemptLogin = async (
.slice(0, 32)
.padStart(
32 + (password.slice(0, 32).length - new Blob([password]).size),
"0"
'0'
)
);
@@ -72,36 +72,36 @@ const attemptLogin = async (
encryptedPrivateKey,
iv,
tag,
privateKey,
privateKey
});
const userOrgs = await getOrganizations();
const userOrgsData = userOrgs.map((org) => org._id);
let orgToLogin;
if (userOrgsData.includes(localStorage.getItem("orgData.id"))) {
orgToLogin = localStorage.getItem("orgData.id");
if (userOrgsData.includes(localStorage.getItem('orgData.id'))) {
orgToLogin = localStorage.getItem('orgData.id');
} else {
orgToLogin = userOrgsData[0];
localStorage.setItem("orgData.id", orgToLogin);
localStorage.setItem('orgData.id', orgToLogin);
}
let orgUserProjects = await getOrganizationUserProjects({
orgId: orgToLogin,
orgId: orgToLogin
});
orgUserProjects = orgUserProjects?.map((project) => project._id);
let projectToLogin;
if (
orgUserProjects.includes(localStorage.getItem("projectData.id"))
orgUserProjects.includes(localStorage.getItem('projectData.id'))
) {
projectToLogin = localStorage.getItem("projectData.id");
projectToLogin = localStorage.getItem('projectData.id');
} else {
try {
projectToLogin = orgUserProjects[0];
localStorage.setItem("projectData.id", projectToLogin);
localStorage.setItem('projectData.id', projectToLogin);
} catch (error) {
console.log("ERROR: User likely has no projects. ", error);
console.log('ERROR: User likely has no projects. ', error);
}
}
@@ -110,38 +110,38 @@ const attemptLogin = async (
await pushKeys({
obj: {
DATABASE_URL: [
"mongodb+srv://${DB_USERNAME}:${DB_PASSWORD}@mongodb.net",
"personal",
'mongodb+srv://${DB_USERNAME}:${DB_PASSWORD}@mongodb.net',
'personal'
],
DB_USERNAME: ["user1234", "personal"],
DB_PASSWORD: ["ah8jak3hk8dhiu4dw7whxwe1l", "personal"],
DB_USERNAME: ['user1234', 'personal'],
DB_PASSWORD: ['ah8jak3hk8dhiu4dw7whxwe1l', 'personal'],
TWILIO_AUTH_TOKEN: [
"hgSIwDAKvz8PJfkj6xkzYqzGmAP3HLuG",
"shared",
'hgSIwDAKvz8PJfkj6xkzYqzGmAP3HLuG',
'shared'
],
WEBSITE_URL: ["http://localhost:3000", "shared"],
STRIPE_SECRET_KEY: ["sk_test_7348oyho4hfq398HIUOH78", "shared"],
WEBSITE_URL: ['http://localhost:3000', 'shared'],
STRIPE_SECRET_KEY: ['sk_test_7348oyho4hfq398HIUOH78', 'shared']
},
workspaceId: projectToLogin,
env: "Development",
env: 'Development'
});
}
if (email) {
telemetry.identify(email);
telemetry.capture("User Logged In");
telemetry.capture('User Logged In');
}
if (isLogin) {
router.push("/dashboard/");
router.push('/dashboard/');
}
} catch (error) {
setErrorLogin(true);
console.log("Login response not available");
console.log('Login response not available');
}
}
);
} catch (error) {
console.log("Something went wrong during authentication");
console.log('Something went wrong during authentication');
}
return true;
};
@@ -1,98 +0,0 @@
import issueBackupPrivateKey from "~/pages/api/auth/IssueBackupPrivateKey";
import SRP1 from "~/pages/api/auth/SRP1";
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");
/**
* This function loggs in the user (whether it's right after signup, or a normal login)
* @param {*} email
* @param {*} password
* @param {*} setErrorLogin
* @param {*} router
* @param {*} isSignUp
* @returns
*/
const issueBackupKey = async ({
email,
password,
personalName,
setBackupKeyError,
setBackupKeyIssued,
}) => {
try {
setBackupKeyError(false);
setBackupKeyIssued(false);
clientPassword.init(
{
username: email,
password: password,
},
async () => {
const clientPublicKey = clientPassword.getPublicKey();
let serverPublicKey, salt;
try {
const res = await SRP1({
clientPublicKey: clientPublicKey,
});
serverPublicKey = res.serverPublicKey;
salt = res.salt;
} catch (err) {
setBackupKeyError(true);
console.log("Wrong current password", err, 1);
}
clientPassword.setSalt(salt);
clientPassword.setServerPublicKey(serverPublicKey);
const clientProof = clientPassword.getProof(); // called M1
const generatedKey = crypto.randomBytes(16).toString("hex");
clientKey.init(
{
username: email,
password: generatedKey,
},
async () => {
clientKey.createVerifier(async (err, result) => {
let { ciphertext, iv, tag } = Aes256Gcm.encrypt(
localStorage.getItem("PRIVATE_KEY"),
generatedKey
);
const res = await issueBackupPrivateKey({
encryptedPrivateKey: ciphertext,
iv,
tag,
salt: result.salt,
verifier: result.verifier,
clientProof,
});
if (res.status == 400) {
setBackupKeyError(true);
} else if (res.status == 200) {
generateBackupPDF(personalName, email, generatedKey);
setBackupKeyIssued(true);
}
});
}
);
}
);
} catch (error) {
setBackupKeyError(true);
console.log("Failed to issue a backup key");
}
return true;
};
export default issueBackupKey;
@@ -0,0 +1,112 @@
import issueBackupPrivateKey from '~/pages/api/auth/IssueBackupPrivateKey';
import SRP1 from '~/pages/api/auth/SRP1';
import { tempLocalStorage } from '../checks/tempLocalStorage';
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 Props {
email: string;
password: string;
personalName: string;
setBackupKeyError: any;
setBackupKeyIssued: any;
}
/**
* This function loggs in the user (whether it's right after signup, or a normal login)
* @param {*} email
* @param {*} password
* @param {*} setErrorLogin
* @param {*} router
* @param {*} isSignUp
* @returns
*/
const issueBackupKey = async ({
email,
password,
personalName,
setBackupKeyError,
setBackupKeyIssued
}: Props) => {
try {
setBackupKeyError(false);
setBackupKeyIssued(false);
clientPassword.init(
{
username: email,
password: password
},
async () => {
const clientPublicKey = clientPassword.getPublicKey();
let serverPublicKey, salt;
try {
const res = await SRP1({
clientPublicKey: clientPublicKey
});
serverPublicKey = res.serverPublicKey;
salt = res.salt;
} catch (err) {
setBackupKeyError(true);
console.log('Wrong current password', err, 1);
}
clientPassword.setSalt(salt);
clientPassword.setServerPublicKey(serverPublicKey);
const clientProof = clientPassword.getProof(); // called M1
const generatedKey = crypto.randomBytes(16).toString('hex');
clientKey.init(
{
username: email,
password: generatedKey
},
async () => {
clientKey.createVerifier(
async (_: any, result: { salt: string; verifier: string }) => {
// TODO: Fix this
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const { ciphertext, iv, tag } = Aes256Gcm.encrypt(
tempLocalStorage('PRIVATE_KEY'),
generatedKey
);
const res = await issueBackupPrivateKey({
encryptedPrivateKey: ciphertext,
iv,
tag,
salt: result.salt,
verifier: result.verifier,
clientProof
});
if (res && res.status == 400) {
setBackupKeyError(true);
} else if (res && res.status == 200) {
generateBackupPDF(personalName, email, generatedKey);
setBackupKeyIssued(true);
}
}
);
}
);
}
);
} catch (error) {
setBackupKeyError(true);
console.log('Failed to issue a backup key');
}
return true;
};
export default issueBackupKey;
@@ -6,21 +6,21 @@ const LINE =
* @param {Buffer} src - source buffer
* @returns {String} text - text of buffer
*/
function parse(src) {
const obj = {};
function parse(src: Buffer) {
const obj: Record<string, string> = {};
// Convert buffer to string
let lines = src.toString();
// Convert line breaks to same format
lines = lines.replace(/\r\n?/gm, "\n");
lines = lines.replace(/\r\n?/gm, '\n');
let match;
while ((match = LINE.exec(lines)) != null) {
const key = match[1];
// Default undefined or null to empty string
let value = match[2] || "";
let value = match[2] || '';
// Remove whitespace
value = value.trim();
@@ -29,12 +29,12 @@ function parse(src) {
const maybeQuote = value[0];
// Remove surrounding quotes
value = value.replace(/^(['"`])([\s\S]*)\1$/gm, "$2");
value = value.replace(/^(['"`])([\s\S]*)\1$/gm, '$2');
// Expand newlines if double quoted
if (maybeQuote === '"') {
value = value.replace(/\\n/g, "\n");
value = value.replace(/\\r/g, "\r");
value = value.replace(/\\n/g, '\n');
value = value.replace(/\\r/g, '\r');
}
// Add to object
@@ -3,19 +3,19 @@
* @returns
*/
const guidGenerator = () => {
var S4 = function () {
const S4 = function () {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
};
return (
S4() +
S4() +
"-" +
'-' +
S4() +
"-" +
'-' +
S4() +
"-" +
'-' +
S4() +
"-" +
'-' +
S4() +
S4() +
S4()
@@ -1,22 +1,30 @@
import getSecrets from "~/pages/api/files/GetSecrets";
import getSecrets from '~/pages/api/files/GetSecrets';
import { envMapping } from "../../../public/data/frequentConstants";
import guidGenerator from "../randomId";
import { envMapping } from '../../../public/data/frequentConstants';
import guidGenerator from '../randomId';
const {
decryptAssymmetric,
decryptSymmetric,
} = require("../cryptography/crypto");
const nacl = require("tweetnacl");
nacl.util = require("tweetnacl-util");
decryptSymmetric
} = require('../cryptography/crypto');
const nacl = require('tweetnacl');
nacl.util = require('tweetnacl-util');
interface Props {
env: keyof typeof envMapping;
setFileState: any;
setIsKeyAvailable: any;
setData: any;
workspaceId: string;
}
const getSecretsForProject = async ({
env,
setFileState,
setIsKeyAvailable,
setData,
workspaceId,
}) => {
workspaceId
}: Props) => {
try {
let file;
try {
@@ -24,44 +32,47 @@ const getSecretsForProject = async ({
setFileState(file);
} catch (error) {
console.log("ERROR: Not able to access the latest file");
console.log('ERROR: Not able to access the latest file');
}
// This is called isKeyAvilable but what it really means is if a person is able to create new key pairs
setIsKeyAvailable(
!file.key ? (file.secrets.length == 0 ? true : false) : true
);
setIsKeyAvailable(!file.key ? file.secrets.length == 0 : true);
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY");
const PRIVATE_KEY = localStorage.getItem('PRIVATE_KEY');
let tempFileState = [];
const tempFileState: { key: string; value: string; type: string }[] = [];
if (file.key) {
// assymmetrically decrypt symmetric key with local private key
const key = decryptAssymmetric({
ciphertext: file.key.encryptedKey,
nonce: file.key.nonce,
publicKey: file.key.sender.publicKey,
privateKey: PRIVATE_KEY,
privateKey: PRIVATE_KEY
});
<<<<<<< HEAD:frontend/components/utilities/secrets/getSecretsForProject.js
file.secrets.map((secretPair) => {
=======
file.secrets.map((secretPair: any) => {
>>>>>>> 158c51ff3cbcd9a8eab6c44e728232d79a1cbab9:frontend/components/utilities/secrets/getSecretsForProject.ts
// decrypt .env file with symmetric key
const plainTextKey = decryptSymmetric({
ciphertext: secretPair.secretKey.ciphertext,
iv: secretPair.secretKey.iv,
tag: secretPair.secretKey.tag,
key,
key
});
const plainTextValue = decryptSymmetric({
ciphertext: secretPair.secretValue.ciphertext,
iv: secretPair.secretValue.iv,
tag: secretPair.secretValue.tag,
key,
key
});
tempFileState.push({
key: plainTextKey,
value: plainTextValue,
type: secretPair.type,
type: secretPair.type
});
});
}
@@ -71,9 +82,9 @@ const getSecretsForProject = async ({
tempFileState.map((line, index) => [
guidGenerator(),
index,
line["key"],
line["value"],
line["type"],
line['key'],
line['value'],
line['type']
])
// .sort((a, b) =>
// sortMethod == "alphabetical"
@@ -84,12 +95,12 @@ const getSecretsForProject = async ({
return tempFileState.map((line, index) => [
guidGenerator(),
index,
line["key"],
line["value"],
line["type"],
line['key'],
line['value'],
line['type']
]);
} catch (error) {
console.log("Something went wrong during accessing or decripting secrets.");
console.log('Something went wrong during accessing or decripting secrets.');
}
return true;
};
@@ -1,74 +0,0 @@
import publicKeyInfical from "~/pages/api/auth/publicKeyInfisical";
import changeHerokuConfigVars from "~/pages/api/integrations/ChangeHerokuConfigVars";
const crypto = require("crypto");
const {
encryptSymmetric,
encryptAssymmetric,
} = require("../cryptography/crypto");
const nacl = require("tweetnacl");
nacl.util = require("tweetnacl-util");
const pushKeysIntegration = async ({ obj, integrationId }) => {
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY");
let randomBytes = crypto.randomBytes(16).toString("hex");
const secrets = Object.keys(obj).map((key) => {
// encrypt key
const {
ciphertext: ciphertextKey,
iv: ivKey,
tag: tagKey,
} = encryptSymmetric({
plaintext: key,
key: randomBytes,
});
// encrypt value
const {
ciphertext: ciphertextValue,
iv: ivValue,
tag: tagValue,
} = encryptSymmetric({
plaintext: obj[key],
key: randomBytes,
});
const visibility = "shared";
return {
ciphertextKey,
ivKey,
tagKey,
hashKey: crypto.createHash("sha256").update(key).digest("hex"),
ciphertextValue,
ivValue,
tagValue,
hashValue: crypto.createHash("sha256").update(obj[key]).digest("hex"),
type: visibility,
};
});
// obtain public keys of all receivers (i.e. members in workspace)
let publicKeyInfisical = await publicKeyInfical();
publicKeyInfisical = (await publicKeyInfisical.json()).publicKey;
// assymmetrically encrypt key with each receiver public keys
const { ciphertext, nonce } = encryptAssymmetric({
plaintext: randomBytes,
publicKey: publicKeyInfisical,
privateKey: PRIVATE_KEY,
});
const key = {
encryptedKey: ciphertext,
nonce,
};
changeHerokuConfigVars({ integrationId, key, secrets });
};
export default pushKeysIntegration;
@@ -0,0 +1,79 @@
import publicKeyInfical from '~/pages/api/auth/publicKeyInfisical';
import changeHerokuConfigVars from '~/pages/api/integrations/ChangeHerokuConfigVars';
const crypto = require('crypto');
const {
encryptSymmetric,
encryptAssymmetric
} = require('../cryptography/crypto');
const nacl = require('tweetnacl');
nacl.util = require('tweetnacl-util');
interface Props {
obj: Record<string, string>;
integrationId: string;
}
const pushKeysIntegration = async ({ obj, integrationId }: Props) => {
const PRIVATE_KEY = localStorage.getItem('PRIVATE_KEY');
const randomBytes = crypto.randomBytes(16).toString('hex');
const secrets = Object.keys(obj).map((key) => {
// encrypt key
const {
ciphertext: ciphertextKey,
iv: ivKey,
tag: tagKey
} = encryptSymmetric({
plaintext: key,
key: randomBytes
});
// encrypt value
const {
ciphertext: ciphertextValue,
iv: ivValue,
tag: tagValue
} = encryptSymmetric({
plaintext: obj[key],
key: randomBytes
});
const visibility = 'shared';
return {
ciphertextKey,
ivKey,
tagKey,
hashKey: crypto.createHash('sha256').update(key).digest('hex'),
ciphertextValue,
ivValue,
tagValue,
hashValue: crypto.createHash('sha256').update(obj[key]).digest('hex'),
type: visibility
};
});
// obtain public keys of all receivers (i.e. members in workspace)
const publicKeyInfisical = await publicKeyInfical();
const publicKey = (await publicKeyInfisical.json()).publicKey;
// assymmetrically encrypt key with each receiver public keys
const { ciphertext, nonce } = encryptAssymmetric({
plaintext: randomBytes,
publicKey,
privateKey: PRIVATE_KEY
});
const key = {
encryptedKey: ciphertext,
nonce
};
changeHerokuConfigVars({ integrationId, key, secrets });
};
export default pushKeysIntegration;