mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-05 14:26:38 +00:00
Fix merge conflicts frontend integrations
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
import * as Sentry from '@sentry/node';
|
import * as Sentry from '@sentry/node';
|
||||||
@@ -6,16 +7,16 @@ const jsrp = require('jsrp');
|
|||||||
import { User } from '../models';
|
import { User } from '../models';
|
||||||
import { createToken, issueTokens, clearTokens } from '../helpers/auth';
|
import { createToken, issueTokens, clearTokens } from '../helpers/auth';
|
||||||
import {
|
import {
|
||||||
NODE_ENV,
|
NODE_ENV,
|
||||||
JWT_AUTH_LIFETIME,
|
JWT_AUTH_LIFETIME,
|
||||||
JWT_AUTH_SECRET,
|
JWT_AUTH_SECRET,
|
||||||
JWT_REFRESH_SECRET
|
JWT_REFRESH_SECRET
|
||||||
} from '../config';
|
} from '../config';
|
||||||
|
|
||||||
declare module 'jsonwebtoken' {
|
declare module 'jsonwebtoken' {
|
||||||
export interface UserIDJwtPayload extends jwt.JwtPayload {
|
export interface UserIDJwtPayload extends jwt.JwtPayload {
|
||||||
userId: string;
|
userId: string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const clientPublicKeys: any = {};
|
const clientPublicKeys: any = {};
|
||||||
@@ -27,47 +28,45 @@ const clientPublicKeys: any = {};
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const login1 = async (req: Request, res: Response) => {
|
export const login1 = async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
const {
|
const {
|
||||||
email,
|
email,
|
||||||
clientPublicKey
|
clientPublicKey
|
||||||
}: { email: string; clientPublicKey: string } = req.body;
|
}: { email: string; clientPublicKey: string } = req.body;
|
||||||
|
|
||||||
const user = await User.findOne({
|
const user = await User.findOne({
|
||||||
email
|
email
|
||||||
}).select('+salt +verifier');
|
}).select('+salt +verifier');
|
||||||
|
|
||||||
|
if (!user) throw new Error('Failed to find user');
|
||||||
|
|
||||||
if (!user) throw new Error('Failed to find user');
|
const server = new jsrp.server();
|
||||||
|
server.init(
|
||||||
|
{
|
||||||
|
salt: user.salt,
|
||||||
|
verifier: user.verifier
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
// generate server-side public key
|
||||||
|
const serverPublicKey = server.getPublicKey();
|
||||||
|
clientPublicKeys[email] = {
|
||||||
|
clientPublicKey,
|
||||||
|
serverBInt: bigintConversion.bigintToBuf(server.bInt)
|
||||||
|
};
|
||||||
|
|
||||||
const server = new jsrp.server();
|
return res.status(200).send({
|
||||||
server.init(
|
serverPublicKey,
|
||||||
{
|
salt: user.salt
|
||||||
salt: user.salt,
|
});
|
||||||
verifier: user.verifier
|
}
|
||||||
},
|
);
|
||||||
() => {
|
} catch (err) {
|
||||||
// generate server-side public key
|
Sentry.setUser(null);
|
||||||
const serverPublicKey = server.getPublicKey();
|
Sentry.captureException(err);
|
||||||
clientPublicKeys[email] = {
|
return res.status(400).send({
|
||||||
clientPublicKey,
|
message: 'Failed to start authentication process'
|
||||||
serverBInt: bigintConversion.bigintToBuf(server.bInt)
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
return res.status(200).send({
|
|
||||||
serverPublicKey,
|
|
||||||
salt: user.salt
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to start authentication process'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,59 +77,59 @@ export const login1 = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const login2 = async (req: Request, res: Response) => {
|
export const login2 = async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
const { email, clientProof } = req.body;
|
const { email, clientProof } = req.body;
|
||||||
const user = await User.findOne({
|
const user = await User.findOne({
|
||||||
email
|
email
|
||||||
}).select('+salt +verifier +publicKey +encryptedPrivateKey +iv +tag');
|
}).select('+salt +verifier +publicKey +encryptedPrivateKey +iv +tag');
|
||||||
|
|
||||||
if (!user) throw new Error('Failed to find user');
|
if (!user) throw new Error('Failed to find user');
|
||||||
|
|
||||||
const server = new jsrp.server();
|
const server = new jsrp.server();
|
||||||
server.init(
|
server.init(
|
||||||
{
|
{
|
||||||
salt: user.salt,
|
salt: user.salt,
|
||||||
verifier: user.verifier,
|
verifier: user.verifier,
|
||||||
b: clientPublicKeys[email].serverBInt
|
b: clientPublicKeys[email].serverBInt
|
||||||
},
|
},
|
||||||
async () => {
|
async () => {
|
||||||
server.setClientPublicKey(clientPublicKeys[email].clientPublicKey);
|
server.setClientPublicKey(clientPublicKeys[email].clientPublicKey);
|
||||||
|
|
||||||
// compare server and client shared keys
|
// compare server and client shared keys
|
||||||
if (server.checkClientProof(clientProof)) {
|
if (server.checkClientProof(clientProof)) {
|
||||||
// issue tokens
|
// issue tokens
|
||||||
const tokens = await issueTokens({ userId: user._id.toString() });
|
const tokens = await issueTokens({ userId: user._id.toString() });
|
||||||
|
|
||||||
// store (refresh) token in httpOnly cookie
|
// store (refresh) token in httpOnly cookie
|
||||||
res.cookie('jid', tokens.refreshToken, {
|
res.cookie('jid', tokens.refreshToken, {
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
path: '/token',
|
path: '/token',
|
||||||
sameSite: "strict",
|
sameSite: 'strict',
|
||||||
secure: NODE_ENV === 'production' ? true : false
|
secure: NODE_ENV === 'production' ? true : false
|
||||||
});
|
});
|
||||||
|
|
||||||
// return (access) token in response
|
// return (access) token in response
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
token: tokens.token,
|
token: tokens.token,
|
||||||
publicKey: user.publicKey,
|
publicKey: user.publicKey,
|
||||||
encryptedPrivateKey: user.encryptedPrivateKey,
|
encryptedPrivateKey: user.encryptedPrivateKey,
|
||||||
iv: user.iv,
|
iv: user.iv,
|
||||||
tag: user.tag
|
tag: user.tag
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(400).send({
|
return res.status(400).send({
|
||||||
message: 'Failed to authenticate. Try again?'
|
message: 'Failed to authenticate. Try again?'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Sentry.setUser(null);
|
Sentry.setUser(null);
|
||||||
Sentry.captureException(err);
|
Sentry.captureException(err);
|
||||||
return res.status(400).send({
|
return res.status(400).send({
|
||||||
message: 'Failed to authenticate. Try again?'
|
message: 'Failed to authenticate. Try again?'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -140,29 +139,29 @@ export const login2 = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const logout = async (req: Request, res: Response) => {
|
export const logout = async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
await clearTokens({
|
await clearTokens({
|
||||||
userId: req.user._id.toString()
|
userId: req.user._id.toString()
|
||||||
});
|
});
|
||||||
|
|
||||||
// clear httpOnly cookie
|
// clear httpOnly cookie
|
||||||
res.cookie('jid', '', {
|
res.cookie('jid', '', {
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
path: '/token',
|
path: '/token',
|
||||||
sameSite: "strict",
|
sameSite: 'strict',
|
||||||
secure: NODE_ENV === 'production' ? true : false
|
secure: NODE_ENV === 'production' ? true : false
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Sentry.setUser({ email: req.user.email });
|
Sentry.setUser({ email: req.user.email });
|
||||||
Sentry.captureException(err);
|
Sentry.captureException(err);
|
||||||
return res.status(400).send({
|
return res.status(400).send({
|
||||||
message: 'Failed to logout'
|
message: 'Failed to logout'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Successfully logged out.'
|
message: 'Successfully logged out.'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -172,9 +171,9 @@ export const logout = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const checkAuth = async (req: Request, res: Response) =>
|
export const checkAuth = async (req: Request, res: Response) =>
|
||||||
res.status(200).send({
|
res.status(200).send({
|
||||||
message: 'Authenticated'
|
message: 'Authenticated'
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return new token by redeeming refresh token
|
* Return new token by redeeming refresh token
|
||||||
@@ -183,42 +182,41 @@ export const checkAuth = async (req: Request, res: Response) =>
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getNewToken = async (req: Request, res: Response) => {
|
export const getNewToken = async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
const refreshToken = req.cookies.jid;
|
const refreshToken = req.cookies.jid;
|
||||||
|
|
||||||
if (!refreshToken) {
|
if (!refreshToken) {
|
||||||
throw new Error('Failed to find token in request cookies');
|
throw new Error('Failed to find token in request cookies');
|
||||||
}
|
}
|
||||||
|
|
||||||
const decodedToken = <jwt.UserIDJwtPayload>(
|
const decodedToken = <jwt.UserIDJwtPayload>(
|
||||||
jwt.verify(refreshToken, JWT_REFRESH_SECRET)
|
jwt.verify(refreshToken, JWT_REFRESH_SECRET)
|
||||||
);
|
);
|
||||||
|
|
||||||
const user = await User.findOne({
|
const user = await User.findOne({
|
||||||
_id: decodedToken.userId
|
_id: decodedToken.userId
|
||||||
}).select('+publicKey');
|
}).select('+publicKey');
|
||||||
|
|
||||||
if (!user) throw new Error('Failed to authenticate unfound user');
|
if (!user) throw new Error('Failed to authenticate unfound user');
|
||||||
if (!user?.publicKey)
|
if (!user?.publicKey)
|
||||||
throw new Error('Failed to authenticate not fully set up account');
|
throw new Error('Failed to authenticate not fully set up account');
|
||||||
|
|
||||||
const token = createToken({
|
const token = createToken({
|
||||||
payload: {
|
payload: {
|
||||||
userId: decodedToken.userId
|
userId: decodedToken.userId
|
||||||
},
|
},
|
||||||
expiresIn: JWT_AUTH_LIFETIME,
|
expiresIn: JWT_AUTH_LIFETIME,
|
||||||
secret: JWT_AUTH_SECRET
|
secret: JWT_AUTH_SECRET
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
token
|
token
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
} catch (err) {
|
Sentry.setUser(null);
|
||||||
Sentry.setUser(null);
|
Sentry.captureException(err);
|
||||||
Sentry.captureException(err);
|
return res.status(400).send({
|
||||||
return res.status(400).send({
|
message: 'Invalid request'
|
||||||
message: 'Invalid request'
|
});
|
||||||
});
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
+14
-18
@@ -5,28 +5,24 @@ import { requireAuth, validateRequest } from '../middleware';
|
|||||||
import { authController } from '../controllers';
|
import { authController } from '../controllers';
|
||||||
import { loginLimiter } from '../helpers/rateLimiter';
|
import { loginLimiter } from '../helpers/rateLimiter';
|
||||||
|
|
||||||
|
router.post('/token', validateRequest, authController.getNewToken);
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
'/token',
|
'/login1',
|
||||||
validateRequest,
|
loginLimiter,
|
||||||
authController.getNewToken
|
body('email').exists().trim().notEmpty(),
|
||||||
|
body('clientPublicKey').exists().trim().notEmpty(),
|
||||||
|
validateRequest,
|
||||||
|
authController.login1
|
||||||
);
|
);
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
'/login1',
|
'/login2',
|
||||||
loginLimiter,
|
loginLimiter,
|
||||||
body('email').exists().trim().notEmpty(),
|
body('email').exists().trim().notEmpty(),
|
||||||
body('clientPublicKey').exists().trim().notEmpty(),
|
body('clientProof').exists().trim().notEmpty(),
|
||||||
validateRequest,
|
validateRequest,
|
||||||
authController.login1
|
authController.login2
|
||||||
);
|
|
||||||
|
|
||||||
router.post(
|
|
||||||
'/login2',
|
|
||||||
loginLimiter,
|
|
||||||
body('email').exists().trim().notEmpty(),
|
|
||||||
body('clientProof').exists().trim().notEmpty(),
|
|
||||||
validateRequest,
|
|
||||||
authController.login2
|
|
||||||
);
|
);
|
||||||
|
|
||||||
router.post('/logout', requireAuth, authController.logout);
|
router.post('/logout', requireAuth, authController.logout);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from 'react';
|
||||||
import Image from "next/image";
|
import Image from 'next/image';
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
import { publicPaths } from "~/const";
|
import { publicPaths } from '~/const';
|
||||||
import checkAuth from "~/pages/api/auth/CheckAuth";
|
import checkAuth from '~/pages/api/auth/CheckAuth';
|
||||||
|
|
||||||
// #TODO: finish spinner only when the data loads fully
|
// #TODO: finish spinner only when the data loads fully
|
||||||
// #TODO: Redirect somewhere if the page does not exist
|
// #TODO: Redirect somewhere if the page does not exist
|
||||||
@@ -22,16 +22,16 @@ export default function RouteGuard({ children }) {
|
|||||||
// #TODO: add the loading page when not yet authorized.
|
// #TODO: add the loading page when not yet authorized.
|
||||||
const hideContent = () => setAuthorized(false);
|
const hideContent = () => setAuthorized(false);
|
||||||
// const onError = () => setAuthorized(true)
|
// const onError = () => setAuthorized(true)
|
||||||
router.events.on("routeChangeStart", hideContent);
|
router.events.on('routeChangeStart', hideContent);
|
||||||
// router.events.on("routeChangeError", onError);
|
// router.events.on("routeChangeError", onError);
|
||||||
|
|
||||||
// on route change complete - run auth check
|
// on route change complete - run auth check
|
||||||
router.events.on("routeChangeComplete", authCheck);
|
router.events.on('routeChangeComplete', authCheck);
|
||||||
|
|
||||||
// unsubscribe from events in useEffect return function
|
// unsubscribe from events in useEffect return function
|
||||||
return () => {
|
return () => {
|
||||||
router.events.off("routeChangeStart", hideContent);
|
router.events.off('routeChangeStart', hideContent);
|
||||||
router.events.off("routeChangeComplete", authCheck);
|
router.events.off('routeChangeComplete', authCheck);
|
||||||
// router.events.off("routeChangeError", onError);
|
// router.events.off("routeChangeError", onError);
|
||||||
};
|
};
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
@@ -43,7 +43,7 @@ export default function RouteGuard({ children }) {
|
|||||||
*/
|
*/
|
||||||
async function authCheck(url) {
|
async function authCheck(url) {
|
||||||
// Make sure that we don't redirect when the user is on the following pages.
|
// Make sure that we don't redirect when the user is on the following pages.
|
||||||
const path = "/" + url.split("?")[0].split("/")[1];
|
const path = '/' + url.split('?')[0].split('/')[1];
|
||||||
|
|
||||||
// Check if the user is authenticated
|
// Check if the user is authenticated
|
||||||
const response = await checkAuth();
|
const response = await checkAuth();
|
||||||
@@ -51,16 +51,16 @@ export default function RouteGuard({ children }) {
|
|||||||
if (!publicPaths.includes(path)) {
|
if (!publicPaths.includes(path)) {
|
||||||
try {
|
try {
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
router.push("/login");
|
router.push('/login');
|
||||||
console.log("Unauthorized to access.");
|
console.log('Unauthorized to access.');
|
||||||
setAuthorized(false);
|
setAuthorized(false);
|
||||||
} else {
|
} else {
|
||||||
setAuthorized(true);
|
setAuthorized(true);
|
||||||
console.log("Authorized to access.");
|
console.log('Authorized to access.');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(
|
console.log(
|
||||||
"Error (probably the authCheck route is stuck again...):",
|
'Error (probably the authCheck route is stuck again...):',
|
||||||
error
|
error
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||||
|
/* eslint-disable no-undef */
|
||||||
|
import posthog from 'posthog-js';
|
||||||
|
|
||||||
|
import { ENV, POSTHOG_API_KEY, POSTHOG_HOST } from '../utilities/config';
|
||||||
|
|
||||||
|
export const initPostHog = () => {
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
// @ts-ignore
|
||||||
|
if (ENV == 'production' && TELEMETRY_CAPTURING_ENABLED) {
|
||||||
|
posthog.init(POSTHOG_API_KEY, {
|
||||||
|
api_host: POSTHOG_HOST
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return posthog;
|
||||||
|
};
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from 'react';
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from 'next/router';
|
||||||
import { faCircle, faEye, faEyeSlash } from "@fortawesome/free-solid-svg-icons";
|
import { faCircle, faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
|
||||||
import guidGenerator from "../utilities/randomId";
|
import guidGenerator from '../utilities/randomId';
|
||||||
|
|
||||||
interface InputFieldProps {
|
interface InputFieldProps {
|
||||||
static?: boolean;
|
static?: boolean;
|
||||||
@@ -23,7 +23,7 @@ interface InputFieldProps {
|
|||||||
|
|
||||||
const InputField = (
|
const InputField = (
|
||||||
props: InputFieldProps &
|
props: InputFieldProps &
|
||||||
Pick<JSX.IntrinsicElements["input"], "autoComplete" | "id">
|
Pick<JSX.IntrinsicElements['input'], 'autoComplete' | 'id'>
|
||||||
) => {
|
) => {
|
||||||
const [passwordVisible, setPasswordVisible] = useState(false);
|
const [passwordVisible, setPasswordVisible] = useState(false);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -75,28 +75,28 @@ const InputField = (
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`group relative flex flex-col justify-center w-full max-w-2xl border ${
|
className={`group relative flex flex-col justify-center w-full max-w-2xl border ${
|
||||||
props.error ? "border-red" : "border-mineshaft-500"
|
props.error ? 'border-red' : 'border-mineshaft-500'
|
||||||
} rounded-md`}
|
} rounded-md`}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
onChange={(e) => props.onChangeHandler(e.target.value)}
|
onChange={(e) => props.onChangeHandler(e.target.value)}
|
||||||
type={passwordVisible === false ? props.type : "text"}
|
type={passwordVisible === false ? props.type : 'text'}
|
||||||
placeholder={props.placeholder}
|
placeholder={props.placeholder}
|
||||||
value={props.value}
|
value={props.value}
|
||||||
required={props.isRequired}
|
required={props.isRequired}
|
||||||
className={`${
|
className={`${
|
||||||
props.blurred
|
props.blurred
|
||||||
? "text-bunker-800 group-hover:text-gray-400 focus:text-gray-400 active:text-gray-400"
|
? 'text-bunker-800 group-hover:text-gray-400 focus:text-gray-400 active:text-gray-400'
|
||||||
: ""
|
: ''
|
||||||
} ${
|
} ${
|
||||||
props.error ? "focus:ring-red/50" : "focus:ring-primary/50"
|
props.error ? 'focus:ring-red/50' : 'focus:ring-primary/50'
|
||||||
} relative peer bg-bunker-800 rounded-md text-gray-400 text-md p-2 w-full min-w-16 outline-none focus:ring-4 duration-200`}
|
} relative peer bg-bunker-800 rounded-md text-gray-400 text-md p-2 w-full min-w-16 outline-none focus:ring-4 duration-200`}
|
||||||
name={props.name}
|
name={props.name}
|
||||||
spellCheck="false"
|
spellCheck="false"
|
||||||
autoComplete={props.autoComplete}
|
autoComplete={props.autoComplete}
|
||||||
id={props.id}
|
id={props.id}
|
||||||
/>
|
/>
|
||||||
{props.label?.includes("Password") && (
|
{props.label?.includes('Password') && (
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setPasswordVisible(!passwordVisible);
|
setPasswordVisible(!passwordVisible);
|
||||||
@@ -114,7 +114,7 @@ const InputField = (
|
|||||||
<div className="peer group-hover:hidden peer-hover:hidden peer-focus:hidden peer-active:invisible absolute h-10 w-fit max-w-xl rounded-md flex items-center text-gray-400/50 text-clip overflow-hidden">
|
<div className="peer group-hover:hidden peer-hover:hidden peer-focus:hidden peer-active:invisible absolute h-10 w-fit max-w-xl rounded-md flex items-center text-gray-400/50 text-clip overflow-hidden">
|
||||||
<p className="ml-2"></p>
|
<p className="ml-2"></p>
|
||||||
{props.value
|
{props.value
|
||||||
.split("")
|
.split('')
|
||||||
.slice(0, 54)
|
.slice(0, 54)
|
||||||
.map(() => (
|
.map(() => (
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from 'next/router';
|
||||||
import { faX } from "@fortawesome/free-solid-svg-icons";
|
import { faX } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
import { reverseEnvMapping } from "../../../public/data/frequentConstants";
|
import { reverseEnvMapping } from '../../../public/data/frequentConstants';
|
||||||
import guidGenerator from "../../utilities/randomId";
|
import guidGenerator from '../../utilities/randomId';
|
||||||
import Button from "../buttons/Button";
|
import Button from '../buttons/Button';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the component that we utilize for the user table - in future, can reuse it for some other purposes too.
|
* This is the component that we utilize for the user table - in future, can reuse it for some other purposes too.
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
import React, { useEffect, useMemo, useState } from "react";
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from 'next/router';
|
||||||
import { faX } from "@fortawesome/free-solid-svg-icons";
|
import { faX } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
import deleteUserFromOrganization from "~/pages/api/organization/deleteUserFromOrganization";
|
import deleteUserFromOrganization from '~/pages/api/organization/deleteUserFromOrganization';
|
||||||
import changeUserRoleInWorkspace from "~/pages/api/workspace/changeUserRoleInWorkspace";
|
import changeUserRoleInWorkspace from '~/pages/api/workspace/changeUserRoleInWorkspace';
|
||||||
import deleteUserFromWorkspace from "~/pages/api/workspace/deleteUserFromWorkspace";
|
import deleteUserFromWorkspace from '~/pages/api/workspace/deleteUserFromWorkspace';
|
||||||
import getLatestFileKey from "~/pages/api/workspace/getLatestFileKey";
|
import getLatestFileKey from '~/pages/api/workspace/getLatestFileKey';
|
||||||
import uploadKeys from "~/pages/api/workspace/uploadKeys";
|
import uploadKeys from '~/pages/api/workspace/uploadKeys';
|
||||||
|
|
||||||
import guidGenerator from "../../utilities/randomId";
|
import guidGenerator from '../../utilities/randomId';
|
||||||
import Button from "../buttons/Button";
|
import Button from '../buttons/Button';
|
||||||
import Listbox from "../Listbox";
|
import Listbox from '../Listbox';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
decryptAssymmetric,
|
decryptAssymmetric,
|
||||||
encryptAssymmetric,
|
encryptAssymmetric
|
||||||
} = require("../../utilities/cryptography/crypto");
|
} = require('../../utilities/cryptography/crypto');
|
||||||
const nacl = require("tweetnacl");
|
const nacl = require('tweetnacl');
|
||||||
nacl.util = require("tweetnacl-util");
|
nacl.util = require('tweetnacl-util');
|
||||||
|
|
||||||
const roles = ["admin", "user"];
|
const roles = ['admin', 'user'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the component that we utilize for the user table - in future, can reuse it for some other purposes too.
|
* This is the component that we utilize for the user table - in future, can reuse it for some other purposes too.
|
||||||
@@ -36,13 +36,13 @@ const UserTable = ({
|
|||||||
isOrg,
|
isOrg,
|
||||||
onClick,
|
onClick,
|
||||||
deleteUser,
|
deleteUser,
|
||||||
setUserIdToBeDeleted,
|
setUserIdToBeDeleted
|
||||||
}) => {
|
}) => {
|
||||||
const [roleSelected, setRoleSelected] = useState(
|
const [roleSelected, setRoleSelected] = useState(
|
||||||
Array(userData?.length).fill(userData.map((user) => user.role))
|
Array(userData?.length).fill(userData.map((user) => user.role))
|
||||||
);
|
);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [myRole, setMyRole] = useState("member");
|
const [myRole, setMyRole] = useState('member');
|
||||||
|
|
||||||
// Delete the row in the table (e.g. a user)
|
// Delete the row in the table (e.g. a user)
|
||||||
// #TODO: Add a pop-up that warns you that the user is going to be deleted.
|
// #TODO: Add a pop-up that warns you that the user is going to be deleted.
|
||||||
@@ -57,7 +57,7 @@ const UserTable = ({
|
|||||||
changeData(userData.filter((v, i) => i !== index));
|
changeData(userData.filter((v, i) => i !== index));
|
||||||
setRoleSelected([
|
setRoleSelected([
|
||||||
...roleSelected.slice(0, index),
|
...roleSelected.slice(0, index),
|
||||||
...roleSelected.slice(index + 1, userData?.length),
|
...roleSelected.slice(index + 1, userData?.length)
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -76,10 +76,10 @@ const UserTable = ({
|
|||||||
status: userData[index].status,
|
status: userData[index].status,
|
||||||
userId: userData[index].userId,
|
userId: userData[index].userId,
|
||||||
membershipId: userData[index].membershipId,
|
membershipId: userData[index].membershipId,
|
||||||
publicKey: userData[index].publicKey,
|
publicKey: userData[index].publicKey
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
...userData.slice(index + 1, userData?.length),
|
...userData.slice(index + 1, userData?.length)
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -88,22 +88,22 @@ const UserTable = ({
|
|||||||
}, [userData, myUser]);
|
}, [userData, myUser]);
|
||||||
|
|
||||||
const grantAccess = async (id, publicKey) => {
|
const grantAccess = async (id, publicKey) => {
|
||||||
let result = await getLatestFileKey({workspaceId: router.query.id});
|
let result = await getLatestFileKey({ workspaceId: router.query.id });
|
||||||
|
|
||||||
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY");
|
const PRIVATE_KEY = localStorage.getItem('PRIVATE_KEY');
|
||||||
|
|
||||||
// assymmetrically decrypt symmetric key with local private key
|
// assymmetrically decrypt symmetric key with local private key
|
||||||
const key = decryptAssymmetric({
|
const key = decryptAssymmetric({
|
||||||
ciphertext: result.latestKey.encryptedKey,
|
ciphertext: result.latestKey.encryptedKey,
|
||||||
nonce: result.latestKey.nonce,
|
nonce: result.latestKey.nonce,
|
||||||
publicKey: result.latestKey.sender.publicKey,
|
publicKey: result.latestKey.sender.publicKey,
|
||||||
privateKey: PRIVATE_KEY,
|
privateKey: PRIVATE_KEY
|
||||||
});
|
});
|
||||||
|
|
||||||
const { ciphertext, nonce } = encryptAssymmetric({
|
const { ciphertext, nonce } = encryptAssymmetric({
|
||||||
plaintext: key,
|
plaintext: key,
|
||||||
publicKey: publicKey,
|
publicKey: publicKey,
|
||||||
privateKey: PRIVATE_KEY,
|
privateKey: PRIVATE_KEY
|
||||||
});
|
});
|
||||||
|
|
||||||
uploadKeys(router.query.id, id, ciphertext, nonce);
|
uploadKeys(router.query.id, id, ciphertext, nonce);
|
||||||
@@ -158,24 +158,24 @@ const UserTable = ({
|
|||||||
</td>
|
</td>
|
||||||
<td className="flex flex-row justify-end pr-8 py-2 border-t border-0.5 border-mineshaft-700">
|
<td className="flex flex-row justify-end pr-8 py-2 border-t border-0.5 border-mineshaft-700">
|
||||||
<div className="flex justify-end mr-6 w-3/4 mx-2 w-full h-full flex flex-row items-center">
|
<div className="flex justify-end mr-6 w-3/4 mx-2 w-full h-full flex flex-row items-center">
|
||||||
{row.status == "granted" &&
|
{row.status == 'granted' &&
|
||||||
((myRole == "admin" && row.role != "owner") ||
|
((myRole == 'admin' && row.role != 'owner') ||
|
||||||
myRole == "owner") &&
|
myRole == 'owner') &&
|
||||||
myUser !== row.email ? (
|
myUser !== row.email ? (
|
||||||
<Listbox
|
<Listbox
|
||||||
selected={row.role}
|
selected={row.role}
|
||||||
onChange={(e) => handleRoleUpdate(index, e)}
|
onChange={(e) => handleRoleUpdate(index, e)}
|
||||||
data={
|
data={
|
||||||
myRole == "owner"
|
myRole == 'owner'
|
||||||
? ["owner", "admin", "member"]
|
? ['owner', 'admin', 'member']
|
||||||
: ["admin", "member"]
|
: ['admin', 'member']
|
||||||
}
|
}
|
||||||
text="Role: "
|
text="Role: "
|
||||||
membershipId={row.membershipId}
|
membershipId={row.membershipId}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
row.status != "invited" &&
|
row.status != 'invited' &&
|
||||||
row.status != "verified" && (
|
row.status != 'verified' && (
|
||||||
<Listbox
|
<Listbox
|
||||||
selected={row.role}
|
selected={row.role}
|
||||||
text="Role: "
|
text="Role: "
|
||||||
@@ -183,8 +183,8 @@ const UserTable = ({
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
{(row.status == "invited" ||
|
{(row.status == 'invited' ||
|
||||||
row.status == "verified") && (
|
row.status == 'verified') && (
|
||||||
<div className="w-full pl-9">
|
<div className="w-full pl-9">
|
||||||
<Button
|
<Button
|
||||||
onButtonPressed={() =>
|
onButtonPressed={() =>
|
||||||
@@ -199,7 +199,7 @@ const UserTable = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{row.status == "completed" && myUser !== row.email && (
|
{row.status == 'completed' && myUser !== row.email && (
|
||||||
<div className="border border-mineshaft-700 rounded-md bg-white/5 hover:bg-primary text-white hover:text-black duration-200">
|
<div className="border border-mineshaft-700 rounded-md bg-white/5 hover:bg-primary text-white hover:text-black duration-200">
|
||||||
<Button
|
<Button
|
||||||
onButtonPressed={() =>
|
onButtonPressed={() =>
|
||||||
@@ -214,7 +214,7 @@ const UserTable = ({
|
|||||||
</div>
|
</div>
|
||||||
{myUser !== row.email &&
|
{myUser !== row.email &&
|
||||||
// row.role != "admin" &&
|
// row.role != "admin" &&
|
||||||
myRole != "member" ? (
|
myRole != 'member' ? (
|
||||||
<div className="opacity-50 hover:opacity-100 flex items-center">
|
<div className="opacity-50 hover:opacity-100 flex items-center">
|
||||||
<Button
|
<Button
|
||||||
onButtonPressed={(e) =>
|
onButtonPressed={(e) =>
|
||||||
|
|||||||
@@ -1,14 +1,29 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
|
|
||||||
import StripeRedirect from "~/pages/api/organization/StripeRedirect";
|
import StripeRedirect from '~/pages/api/organization/StripeRedirect';
|
||||||
|
|
||||||
export default function Plan({ plan }) {
|
import { tempLocalStorage } from '../utilities/checks/tempLocalStorage';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
plan: {
|
||||||
|
name: string;
|
||||||
|
price: string;
|
||||||
|
priceExplanation: string;
|
||||||
|
text: string;
|
||||||
|
subtext: string;
|
||||||
|
buttonTextMain: string;
|
||||||
|
buttonTextSecondary: string;
|
||||||
|
current: boolean;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Plan({ plan }: Props) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`relative flex flex-col justify-between border border-2 min-w-fit w-96 rounded-lg h-68 mr-4 bg-mineshaft-800 ${
|
className={`relative flex flex-col justify-between border-2 min-w-fit w-96 rounded-lg h-68 mr-4 bg-mineshaft-800 ${
|
||||||
(plan.name != "Starter") & (plan.current == true)
|
plan.name != 'Starter' && plan.current == true
|
||||||
? "border-primary"
|
? 'border-primary'
|
||||||
: "border-chicago-700"
|
: 'border-chicago-700'
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
@@ -36,7 +51,7 @@ export default function Plan({ plan }) {
|
|||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
{plan.current == false ? (
|
{plan.current == false ? (
|
||||||
<>
|
<>
|
||||||
{plan.buttonTextMain == "Schedule a Demo" ? (
|
{plan.buttonTextMain == 'Schedule a Demo' ? (
|
||||||
<a href="/scheduledemo" target='_blank rel="noopener"'>
|
<a href="/scheduledemo" target='_blank rel="noopener"'>
|
||||||
<div className="relative z-10 mx-5 mt-3 mb-4 py-2 px-4 border border-1 border-gray-600 hover:text-black hover:border-primary text-gray-400 font-semibold hover:bg-primary bg-bunker duration-200 cursor-pointer rounded-md flex w-max">
|
<div className="relative z-10 mx-5 mt-3 mb-4 py-2 px-4 border border-1 border-gray-600 hover:text-black hover:border-primary text-gray-400 font-semibold hover:bg-primary bg-bunker duration-200 cursor-pointer rounded-md flex w-max">
|
||||||
{plan.buttonTextMain}
|
{plan.buttonTextMain}
|
||||||
@@ -45,15 +60,15 @@ export default function Plan({ plan }) {
|
|||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
className={`relative z-10 mx-5 mt-3 mb-4 py-2 px-4 border border-1 border-gray-600 text-gray-400 font-semibold ${
|
className={`relative z-10 mx-5 mt-3 mb-4 py-2 px-4 border border-1 border-gray-600 text-gray-400 font-semibold ${
|
||||||
plan.buttonTextMain == "Downgrade"
|
plan.buttonTextMain == 'Downgrade'
|
||||||
? "hover:bg-red hover:text-white hover:border-red"
|
? 'hover:bg-red hover:text-white hover:border-red'
|
||||||
: "hover:bg-primary hover:text-black hover:border-primary"
|
: 'hover:bg-primary hover:text-black hover:border-primary'
|
||||||
} bg-bunker duration-200 cursor-pointer rounded-md flex w-max`}
|
} bg-bunker duration-200 cursor-pointer rounded-md flex w-max`}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
StripeRedirect({
|
StripeRedirect({
|
||||||
orgId: localStorage.getItem("orgData.id"),
|
orgId: tempLocalStorage('orgData.id')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -61,7 +76,10 @@ export default function Plan({ plan }) {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<a href="https://infisical.com/pricing" target='_blank rel="noopener"'>
|
<a
|
||||||
|
href="https://infisical.com/pricing"
|
||||||
|
target='_blank rel="noopener"'
|
||||||
|
>
|
||||||
<div className="relative z-10 text-gray-400 font-semibold hover:text-primary duration-200 cursor-pointer mb-0.5">
|
<div className="relative z-10 text-gray-400 font-semibold hover:text-primary duration-200 cursor-pointer mb-0.5">
|
||||||
{plan.buttonTextSecondary}
|
{plan.buttonTextSecondary}
|
||||||
</div>
|
</div>
|
||||||
@@ -70,9 +88,9 @@ export default function Plan({ plan }) {
|
|||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
className={`h-8 w-full rounded-b-md flex justify-center items-center z-10 ${
|
className={`h-8 w-full rounded-b-md flex justify-center items-center z-10 ${
|
||||||
(plan.name != "Starter") & (plan.current == true)
|
plan.name != 'Starter' && plan.current == true
|
||||||
? "bg-primary"
|
? 'bg-primary'
|
||||||
: "bg-chicago-700"
|
: 'bg-chicago-700'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<p className="text-xs text-black font-semibold">CURRENT PLAN</p>
|
<p className="text-xs text-black font-semibold">CURRENT PLAN</p>
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import React, { SyntheticEvent, useRef } from "react";
|
import React, { SyntheticEvent, useRef } from 'react';
|
||||||
import { faCircle } from "@fortawesome/free-solid-svg-icons";
|
import { faCircle } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
|
||||||
import guidGenerator from "../utilities/randomId";
|
import guidGenerator from '../utilities/randomId';
|
||||||
|
|
||||||
const REGEX = /([$]{.*?})/g;
|
const REGEX = /([$]{.*?})/g;
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ interface DashboardInputFieldProps {
|
|||||||
index: number;
|
index: number;
|
||||||
onChangeHandler: (value: string, index: number) => void;
|
onChangeHandler: (value: string, index: number) => void;
|
||||||
value: string;
|
value: string;
|
||||||
type: "varName" | "value";
|
type: 'varName' | 'value';
|
||||||
blurred: boolean;
|
blurred: boolean;
|
||||||
duplicates: string[];
|
duplicates: string[];
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ const DashboardInputField = ({
|
|||||||
type,
|
type,
|
||||||
value,
|
value,
|
||||||
blurred,
|
blurred,
|
||||||
duplicates,
|
duplicates
|
||||||
}: DashboardInputFieldProps) => {
|
}: DashboardInputFieldProps) => {
|
||||||
const ref = useRef<HTMLDivElement | null>(null);
|
const ref = useRef<HTMLDivElement | null>(null);
|
||||||
const syncScroll = (e: SyntheticEvent<HTMLDivElement>) => {
|
const syncScroll = (e: SyntheticEvent<HTMLDivElement>) => {
|
||||||
@@ -43,8 +43,8 @@ const DashboardInputField = ({
|
|||||||
ref.current.scrollLeft = e.currentTarget.scrollLeft;
|
ref.current.scrollLeft = e.currentTarget.scrollLeft;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (type === "varName") {
|
if (type === 'varName') {
|
||||||
const startsWithNumber = !isNaN(Number(value.charAt(0))) && value != "";
|
const startsWithNumber = !isNaN(Number(value.charAt(0))) && value != '';
|
||||||
const hasDuplicates = duplicates?.includes(value);
|
const hasDuplicates = duplicates?.includes(value);
|
||||||
const error = startsWithNumber || hasDuplicates;
|
const error = startsWithNumber || hasDuplicates;
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ const DashboardInputField = ({
|
|||||||
<div className="flex-col w-full">
|
<div className="flex-col w-full">
|
||||||
<div
|
<div
|
||||||
className={`group relative flex flex-col justify-center w-full max-w-2xl border ${
|
className={`group relative flex flex-col justify-center w-full max-w-2xl border ${
|
||||||
error ? "border-red" : "border-mineshaft-500"
|
error ? 'border-red' : 'border-mineshaft-500'
|
||||||
} rounded-md`}
|
} rounded-md`}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
@@ -62,7 +62,7 @@ const DashboardInputField = ({
|
|||||||
type={type}
|
type={type}
|
||||||
value={value}
|
value={value}
|
||||||
className={`z-10 peer font-mono ph-no-capture bg-bunker-800 rounded-md caret-white text-gray-400 text-md px-2 py-1.5 w-full min-w-16 outline-none focus:ring-2 ${
|
className={`z-10 peer font-mono ph-no-capture bg-bunker-800 rounded-md caret-white text-gray-400 text-md px-2 py-1.5 w-full min-w-16 outline-none focus:ring-2 ${
|
||||||
error ? "focus:ring-red/50" : "focus:ring-primary/50"
|
error ? 'focus:ring-red/50' : 'focus:ring-primary/50'
|
||||||
} duration-200`}
|
} duration-200`}
|
||||||
spellCheck="false"
|
spellCheck="false"
|
||||||
/>
|
/>
|
||||||
@@ -79,7 +79,7 @@ const DashboardInputField = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (type === "value") {
|
} else if (type === 'value') {
|
||||||
return (
|
return (
|
||||||
<div className="flex-col w-full">
|
<div className="flex-col w-full">
|
||||||
<div
|
<div
|
||||||
@@ -91,8 +91,8 @@ const DashboardInputField = ({
|
|||||||
onScroll={syncScroll}
|
onScroll={syncScroll}
|
||||||
className={`${
|
className={`${
|
||||||
blurred
|
blurred
|
||||||
? "text-transparent group-hover:text-transparent focus:text-transparent active:text-transparent"
|
? 'text-transparent group-hover:text-transparent focus:text-transparent active:text-transparent'
|
||||||
: ""
|
: ''
|
||||||
} z-10 peer font-mono ph-no-capture bg-transparent rounded-md caret-white text-transparent text-md px-2 py-1.5 w-full min-w-16 outline-none focus:ring-2 focus:ring-primary/50 duration-200 no-scrollbar no-scrollbar::-webkit-scrollbar`}
|
} z-10 peer font-mono ph-no-capture bg-transparent rounded-md caret-white text-transparent text-md px-2 py-1.5 w-full min-w-16 outline-none focus:ring-2 focus:ring-primary/50 duration-200 no-scrollbar no-scrollbar::-webkit-scrollbar`}
|
||||||
spellCheck="false"
|
spellCheck="false"
|
||||||
/>
|
/>
|
||||||
@@ -100,8 +100,8 @@ const DashboardInputField = ({
|
|||||||
ref={ref}
|
ref={ref}
|
||||||
className={`${
|
className={`${
|
||||||
blurred
|
blurred
|
||||||
? "text-bunker-800 group-hover:text-gray-400 peer-focus:text-gray-400 peer-active:text-gray-400"
|
? 'text-bunker-800 group-hover:text-gray-400 peer-focus:text-gray-400 peer-active:text-gray-400'
|
||||||
: ""
|
: ''
|
||||||
} absolute flex flex-row whitespace-pre font-mono z-0 ph-no-capture max-w-2xl overflow-x-scroll bg-bunker-800 h-9 rounded-md text-gray-400 text-md px-2 py-1.5 w-full min-w-16 outline-none focus:ring-2 focus:ring-primary/50 duration-100 no-scrollbar no-scrollbar::-webkit-scrollbar`}
|
} absolute flex flex-row whitespace-pre font-mono z-0 ph-no-capture max-w-2xl overflow-x-scroll bg-bunker-800 h-9 rounded-md text-gray-400 text-md px-2 py-1.5 w-full min-w-16 outline-none focus:ring-2 focus:ring-primary/50 duration-100 no-scrollbar no-scrollbar::-webkit-scrollbar`}
|
||||||
>
|
>
|
||||||
{value.split(REGEX).map((word, id) => {
|
{value.split(REGEX).map((word, id) => {
|
||||||
@@ -112,7 +112,7 @@ const DashboardInputField = ({
|
|||||||
<span className="ph-no-capture text-yellow-200/80">
|
<span className="ph-no-capture text-yellow-200/80">
|
||||||
{word.slice(2, word.length - 1)}
|
{word.slice(2, word.length - 1)}
|
||||||
</span>
|
</span>
|
||||||
{word.slice(word.length - 1, word.length) == "}" ? (
|
{word.slice(word.length - 1, word.length) == '}' ? (
|
||||||
<span className="ph-no-capture text-yellow">
|
<span className="ph-no-capture text-yellow">
|
||||||
{word.slice(word.length - 1, word.length)}
|
{word.slice(word.length - 1, word.length)}
|
||||||
</span>
|
</span>
|
||||||
@@ -135,7 +135,7 @@ const DashboardInputField = ({
|
|||||||
{blurred && (
|
{blurred && (
|
||||||
<div className="absolute flex flex-row items-center z-20 peer pr-2 bg-bunker-800 group-hover:hidden peer-hover:hidden peer-focus:hidden peer-active:invisible h-9 w-full max-w-2xl rounded-md text-gray-400/50 text-clip">
|
<div className="absolute flex flex-row items-center z-20 peer pr-2 bg-bunker-800 group-hover:hidden peer-hover:hidden peer-focus:hidden peer-active:invisible h-9 w-full max-w-2xl rounded-md text-gray-400/50 text-clip">
|
||||||
<div className="px-2 flex flex-row items-center overflow-x-scroll no-scrollbar no-scrollbar::-webkit-scrollbar">
|
<div className="px-2 flex flex-row items-center overflow-x-scroll no-scrollbar no-scrollbar::-webkit-scrollbar">
|
||||||
{value.split("").map(() => (
|
{value.split('').map(() => (
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
key={guidGenerator()}
|
key={guidGenerator()}
|
||||||
className="text-xxs mx-0.5"
|
className="text-xxs mx-0.5"
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { type ChangeEvent, type DragEvent, useState } from "react";
|
import { type ChangeEvent, type DragEvent, useState } from 'react';
|
||||||
import Image from "next/image";
|
import Image from 'next/image';
|
||||||
import { faUpload } from "@fortawesome/free-solid-svg-icons";
|
import { faUpload } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
|
||||||
import Button from "../basic/buttons/Button";
|
import Button from '../basic/buttons/Button';
|
||||||
import Error from "../basic/Error";
|
import Error from '../basic/Error';
|
||||||
import parse from "../utilities/file";
|
import parse from '../utilities/file';
|
||||||
import guidGenerator from "../utilities/randomId";
|
import guidGenerator from '../utilities/randomId';
|
||||||
|
|
||||||
interface DropZoneProps {
|
interface DropZoneProps {
|
||||||
// TODO: change Data type from any
|
// TODO: change Data type from any
|
||||||
@@ -26,7 +26,7 @@ const DropZone = ({
|
|||||||
errorDragAndDrop,
|
errorDragAndDrop,
|
||||||
setButtonReady,
|
setButtonReady,
|
||||||
keysExist,
|
keysExist,
|
||||||
numCurrentRows,
|
numCurrentRows
|
||||||
}: DropZoneProps) => {
|
}: DropZoneProps) => {
|
||||||
const handleDragEnter = (e: DragEvent) => {
|
const handleDragEnter = (e: DragEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -43,7 +43,7 @@ const DropZone = ({
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
// set dropEffect to copy i.e copy of the source item
|
// set dropEffect to copy i.e copy of the source item
|
||||||
e.dataTransfer.dropEffect = "copy";
|
e.dataTransfer.dropEffect = 'copy';
|
||||||
};
|
};
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -54,7 +54,7 @@ const DropZone = ({
|
|||||||
setTimeout(() => setLoading(false), 5000);
|
setTimeout(() => setLoading(false), 5000);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.dataTransfer.dropEffect = "copy";
|
e.dataTransfer.dropEffect = 'copy';
|
||||||
|
|
||||||
const file = e.dataTransfer.files[0];
|
const file = e.dataTransfer.files[0];
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
@@ -68,7 +68,7 @@ const DropZone = ({
|
|||||||
numCurrentRows + index,
|
numCurrentRows + index,
|
||||||
key,
|
key,
|
||||||
keyPairs[key as keyof typeof keyPairs],
|
keyPairs[key as keyof typeof keyPairs],
|
||||||
"shared",
|
'shared'
|
||||||
]);
|
]);
|
||||||
setData(newData);
|
setData(newData);
|
||||||
setButtonReady(true);
|
setButtonReady(true);
|
||||||
@@ -94,15 +94,15 @@ const DropZone = ({
|
|||||||
reader.onload = (event) => {
|
reader.onload = (event) => {
|
||||||
if (event.target === null || event.target.result === null) return;
|
if (event.target === null || event.target.result === null) return;
|
||||||
const { result } = event.target;
|
const { result } = event.target;
|
||||||
if (typeof result === "string") {
|
if (typeof result === 'string') {
|
||||||
const newData = result
|
const newData = result
|
||||||
.split("\n")
|
.split('\n')
|
||||||
.map((line: string, index: number) => [
|
.map((line: string, index: number) => [
|
||||||
guidGenerator(),
|
guidGenerator(),
|
||||||
numCurrentRows + index,
|
numCurrentRows + index,
|
||||||
line.split("=")[0],
|
line.split('=')[0],
|
||||||
line.split("=").slice(1, line.split("=").length).join("="),
|
line.split('=').slice(1, line.split('=').length).join('='),
|
||||||
"shared",
|
'shared'
|
||||||
]);
|
]);
|
||||||
setData(newData);
|
setData(newData);
|
||||||
setButtonReady(true);
|
setButtonReady(true);
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
import React, { Fragment, useEffect, useState } from "react";
|
import React, { Fragment, useEffect, useState } from 'react';
|
||||||
import Image from "next/image";
|
import Image from 'next/image';
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from 'next/router';
|
||||||
import { faGithub, faSlack } from "@fortawesome/free-brands-svg-icons";
|
import { faGithub, faSlack } from '@fortawesome/free-brands-svg-icons';
|
||||||
import { faCircleQuestion } from "@fortawesome/free-regular-svg-icons";
|
import { faCircleQuestion } from '@fortawesome/free-regular-svg-icons';
|
||||||
import {
|
import {
|
||||||
faAngleDown,
|
faAngleDown,
|
||||||
faBook,
|
faBook,
|
||||||
@@ -12,39 +12,39 @@ import {
|
|||||||
faEnvelope,
|
faEnvelope,
|
||||||
faGear,
|
faGear,
|
||||||
faPlus,
|
faPlus,
|
||||||
faRightFromBracket,
|
faRightFromBracket
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { Menu, Transition } from "@headlessui/react";
|
import { Menu, Transition } from '@headlessui/react';
|
||||||
|
|
||||||
import logout from "~/pages/api/auth/Logout";
|
import logout from '~/pages/api/auth/Logout';
|
||||||
import getOrganization from "~/pages/api/organization/GetOrg";
|
import getOrganization from '~/pages/api/organization/GetOrg';
|
||||||
import getOrganizations from "~/pages/api/organization/getOrgs";
|
import getOrganizations from '~/pages/api/organization/getOrgs';
|
||||||
import getUser from "~/pages/api/user/getUser";
|
import getUser from '~/pages/api/user/getUser';
|
||||||
|
|
||||||
import guidGenerator from "../utilities/randomId";
|
import guidGenerator from '../utilities/randomId';
|
||||||
|
|
||||||
const supportOptions = [
|
const supportOptions = [
|
||||||
[
|
[
|
||||||
<FontAwesomeIcon className="text-lg pl-1.5 pr-3" icon={faSlack} />,
|
<FontAwesomeIcon className="text-lg pl-1.5 pr-3" icon={faSlack} />,
|
||||||
"Join Slack Forum",
|
'Join Slack Forum',
|
||||||
"https://join.slack.com/t/infisical-users/shared_invite/zt-1kdbk07ro-RtoyEt_9E~fyzGo_xQYP6g",
|
'https://join.slack.com/t/infisical-users/shared_invite/zt-1kdbk07ro-RtoyEt_9E~fyzGo_xQYP6g'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
<FontAwesomeIcon className="text-lg pl-1.5 pr-3" icon={faBook} />,
|
<FontAwesomeIcon className="text-lg pl-1.5 pr-3" icon={faBook} />,
|
||||||
"Read Docs",
|
'Read Docs',
|
||||||
"https://infisical.com/docs/getting-started/introduction",
|
'https://infisical.com/docs/getting-started/introduction'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
<FontAwesomeIcon className="text-lg pl-1.5 pr-3" icon={faGithub} />,
|
<FontAwesomeIcon className="text-lg pl-1.5 pr-3" icon={faGithub} />,
|
||||||
"Open a GitHub Issue",
|
'Open a GitHub Issue',
|
||||||
"https://github.com/Infisical/infisical-cli/issues",
|
'https://github.com/Infisical/infisical-cli/issues'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
<FontAwesomeIcon className="text-lg pl-1.5 pr-3" icon={faEnvelope} />,
|
<FontAwesomeIcon className="text-lg pl-1.5 pr-3" icon={faEnvelope} />,
|
||||||
"Send us an Email",
|
'Send us an Email',
|
||||||
"mailto:[email protected]",
|
'mailto:[email protected]'
|
||||||
],
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
export interface ICurrentOrg {
|
export interface ICurrentOrg {
|
||||||
@@ -75,16 +75,16 @@ export default function Navbar() {
|
|||||||
const orgsData = await getOrganizations();
|
const orgsData = await getOrganizations();
|
||||||
setOrgs(orgsData);
|
setOrgs(orgsData);
|
||||||
const currentOrg = await getOrganization({
|
const currentOrg = await getOrganization({
|
||||||
orgId: String(localStorage.getItem("orgData.id")),
|
orgId: String(localStorage.getItem('orgData.id'))
|
||||||
});
|
});
|
||||||
setCurrentOrg(currentOrg);
|
setCurrentOrg(currentOrg);
|
||||||
})();
|
})();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const closeApp = async () => {
|
const closeApp = async () => {
|
||||||
console.log("Logging out...");
|
console.log('Logging out...');
|
||||||
await logout();
|
await logout();
|
||||||
router.push("/login");
|
router.push('/login');
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -163,7 +163,7 @@ export default function Navbar() {
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
router.push("/settings/personal/" + router.query.id)
|
router.push('/settings/personal/' + router.query.id)
|
||||||
}
|
}
|
||||||
className="flex flex-row items-center px-1 mx-1 my-1 hover:bg-white/5 cursor-pointer rounded-md"
|
className="flex flex-row items-center px-1 mx-1 my-1 hover:bg-white/5 cursor-pointer rounded-md"
|
||||||
>
|
>
|
||||||
@@ -173,11 +173,11 @@ export default function Navbar() {
|
|||||||
<div className="flex items-center justify-between w-full">
|
<div className="flex items-center justify-between w-full">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-gray-300 px-2 pt-1 text-sm">
|
<p className="text-gray-300 px-2 pt-1 text-sm">
|
||||||
{" "}
|
{' '}
|
||||||
{user?.firstName} {user?.lastName}
|
{user?.firstName} {user?.lastName}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-gray-400 px-2 pb-1 text-xs">
|
<p className="text-gray-400 px-2 pb-1 text-xs">
|
||||||
{" "}
|
{' '}
|
||||||
{user?.email}
|
{user?.email}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -194,7 +194,7 @@ export default function Navbar() {
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
router.push("/settings/org/" + router.query.id)
|
router.push('/settings/org/' + router.query.id)
|
||||||
}
|
}
|
||||||
className="flex flex-row items-center px-2 mt-2 py-1 hover:bg-white/5 cursor-pointer rounded-md"
|
className="flex flex-row items-center px-2 mt-2 py-1 hover:bg-white/5 cursor-pointer rounded-md"
|
||||||
>
|
>
|
||||||
@@ -217,7 +217,7 @@ export default function Navbar() {
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
router.push("/settings/billing/" + router.query.id)
|
router.push('/settings/billing/' + router.query.id)
|
||||||
}
|
}
|
||||||
className="mt-1 relative flex justify-start cursor-pointer select-none py-2 px-2 rounded-md text-gray-400 hover:bg-white/5 duration-200 hover:text-gray-200"
|
className="mt-1 relative flex justify-start cursor-pointer select-none py-2 px-2 rounded-md text-gray-400 hover:bg-white/5 duration-200 hover:text-gray-200"
|
||||||
>
|
>
|
||||||
@@ -235,7 +235,7 @@ export default function Navbar() {
|
|||||||
<div
|
<div
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
router.push(
|
router.push(
|
||||||
"/settings/org/" + router.query.id + "?invite"
|
'/settings/org/' + router.query.id + '?invite'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
className="relative flex justify-start cursor-pointer select-none py-2 pl-10 pr-4 rounded-md text-gray-400 hover:bg-primary/100 duration-200 hover:text-black hover:font-semibold mt-1"
|
className="relative flex justify-start cursor-pointer select-none py-2 pl-10 pr-4 rounded-md text-gray-400 hover:bg-primary/100 duration-200 hover:text-black hover:font-semibold mt-1"
|
||||||
@@ -255,13 +255,14 @@ export default function Navbar() {
|
|||||||
<div className="flex flex-col items-start px-1 mt-3 mb-2">
|
<div className="flex flex-col items-start px-1 mt-3 mb-2">
|
||||||
{orgs
|
{orgs
|
||||||
.filter(
|
.filter(
|
||||||
(org : { _id: string }) => org._id != localStorage.getItem("orgData.id")
|
(org: { _id: string }) =>
|
||||||
|
org._id != localStorage.getItem('orgData.id')
|
||||||
)
|
)
|
||||||
.map((org : { _id: string; name: string; }) => (
|
.map((org: { _id: string; name: string }) => (
|
||||||
<div
|
<div
|
||||||
key={guidGenerator()}
|
key={guidGenerator()}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
localStorage.setItem("orgData.id", org._id);
|
localStorage.setItem('orgData.id', org._id);
|
||||||
router.reload();
|
router.reload();
|
||||||
}}
|
}}
|
||||||
className="flex flex-row justify-start items-center hover:bg-white/5 w-full p-1.5 cursor-pointer rounded-md"
|
className="flex flex-row justify-start items-center hover:bg-white/5 w-full p-1.5 cursor-pointer rounded-md"
|
||||||
@@ -286,8 +287,8 @@ export default function Navbar() {
|
|||||||
onClick={closeApp}
|
onClick={closeApp}
|
||||||
className={`${
|
className={`${
|
||||||
active
|
active
|
||||||
? "bg-red font-semibold text-white"
|
? 'bg-red font-semibold text-white'
|
||||||
: "text-gray-400"
|
: 'text-gray-400'
|
||||||
} group flex w-full items-center rounded-md px-2 py-2 text-sm`}
|
} group flex w-full items-center rounded-md px-2 py-2 text-sm`}
|
||||||
>
|
>
|
||||||
<div className="relative flex justify-start items-center cursor-pointer select-none">
|
<div className="relative flex justify-start items-center cursor-pointer select-none">
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
import Aes256Gcm from "~/components/utilities/cryptography/aes-256-gcm";
|
import Aes256Gcm from '~/components/utilities/cryptography/aes-256-gcm';
|
||||||
import login1 from "~/pages/api/auth/Login1";
|
import login1 from '~/pages/api/auth/Login1';
|
||||||
import login2 from "~/pages/api/auth/Login2";
|
import login2 from '~/pages/api/auth/Login2';
|
||||||
import getOrganizations from "~/pages/api/organization/getOrgs";
|
import getOrganizations from '~/pages/api/organization/getOrgs';
|
||||||
import getOrganizationUserProjects from "~/pages/api/organization/GetOrgUserProjects";
|
import getOrganizationUserProjects from '~/pages/api/organization/GetOrgUserProjects';
|
||||||
|
|
||||||
import pushKeys from "./secrets/pushKeys";
|
import pushKeys from './secrets/pushKeys';
|
||||||
import { saveTokenToLocalStorage } from "./saveTokenToLocalStorage";
|
import Telemetry from './telemetry/Telemetry';
|
||||||
import SecurityClient from "./SecurityClient";
|
import { saveTokenToLocalStorage } from './saveTokenToLocalStorage';
|
||||||
import Telemetry from "./telemetry/Telemetry";
|
import SecurityClient from './SecurityClient';
|
||||||
|
|
||||||
const nacl = require("tweetnacl");
|
const nacl = require('tweetnacl');
|
||||||
nacl.util = require("tweetnacl-util");
|
nacl.util = require('tweetnacl-util');
|
||||||
const jsrp = require("jsrp");
|
const jsrp = require('jsrp');
|
||||||
const client = new jsrp.client();
|
const client = new jsrp.client();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,7 +37,7 @@ const attemptLogin = async (
|
|||||||
client.init(
|
client.init(
|
||||||
{
|
{
|
||||||
username: email,
|
username: email,
|
||||||
password: password,
|
password: password
|
||||||
},
|
},
|
||||||
async () => {
|
async () => {
|
||||||
const clientPublicKey = client.getPublicKey();
|
const clientPublicKey = client.getPublicKey();
|
||||||
@@ -62,7 +62,7 @@ const attemptLogin = async (
|
|||||||
.slice(0, 32)
|
.slice(0, 32)
|
||||||
.padStart(
|
.padStart(
|
||||||
32 + (password.slice(0, 32).length - new Blob([password]).size),
|
32 + (password.slice(0, 32).length - new Blob([password]).size),
|
||||||
"0"
|
'0'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -72,36 +72,36 @@ const attemptLogin = async (
|
|||||||
encryptedPrivateKey,
|
encryptedPrivateKey,
|
||||||
iv,
|
iv,
|
||||||
tag,
|
tag,
|
||||||
privateKey,
|
privateKey
|
||||||
});
|
});
|
||||||
|
|
||||||
const userOrgs = await getOrganizations();
|
const userOrgs = await getOrganizations();
|
||||||
const userOrgsData = userOrgs.map((org) => org._id);
|
const userOrgsData = userOrgs.map((org) => org._id);
|
||||||
|
|
||||||
let orgToLogin;
|
let orgToLogin;
|
||||||
if (userOrgsData.includes(localStorage.getItem("orgData.id"))) {
|
if (userOrgsData.includes(localStorage.getItem('orgData.id'))) {
|
||||||
orgToLogin = localStorage.getItem("orgData.id");
|
orgToLogin = localStorage.getItem('orgData.id');
|
||||||
} else {
|
} else {
|
||||||
orgToLogin = userOrgsData[0];
|
orgToLogin = userOrgsData[0];
|
||||||
localStorage.setItem("orgData.id", orgToLogin);
|
localStorage.setItem('orgData.id', orgToLogin);
|
||||||
}
|
}
|
||||||
|
|
||||||
let orgUserProjects = await getOrganizationUserProjects({
|
let orgUserProjects = await getOrganizationUserProjects({
|
||||||
orgId: orgToLogin,
|
orgId: orgToLogin
|
||||||
});
|
});
|
||||||
|
|
||||||
orgUserProjects = orgUserProjects?.map((project) => project._id);
|
orgUserProjects = orgUserProjects?.map((project) => project._id);
|
||||||
let projectToLogin;
|
let projectToLogin;
|
||||||
if (
|
if (
|
||||||
orgUserProjects.includes(localStorage.getItem("projectData.id"))
|
orgUserProjects.includes(localStorage.getItem('projectData.id'))
|
||||||
) {
|
) {
|
||||||
projectToLogin = localStorage.getItem("projectData.id");
|
projectToLogin = localStorage.getItem('projectData.id');
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
projectToLogin = orgUserProjects[0];
|
projectToLogin = orgUserProjects[0];
|
||||||
localStorage.setItem("projectData.id", projectToLogin);
|
localStorage.setItem('projectData.id', projectToLogin);
|
||||||
} catch (error) {
|
} 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({
|
await pushKeys({
|
||||||
obj: {
|
obj: {
|
||||||
DATABASE_URL: [
|
DATABASE_URL: [
|
||||||
"mongodb+srv://${DB_USERNAME}:${DB_PASSWORD}@mongodb.net",
|
'mongodb+srv://${DB_USERNAME}:${DB_PASSWORD}@mongodb.net',
|
||||||
"personal",
|
'personal'
|
||||||
],
|
],
|
||||||
DB_USERNAME: ["user1234", "personal"],
|
DB_USERNAME: ['user1234', 'personal'],
|
||||||
DB_PASSWORD: ["ah8jak3hk8dhiu4dw7whxwe1l", "personal"],
|
DB_PASSWORD: ['ah8jak3hk8dhiu4dw7whxwe1l', 'personal'],
|
||||||
TWILIO_AUTH_TOKEN: [
|
TWILIO_AUTH_TOKEN: [
|
||||||
"hgSIwDAKvz8PJfkj6xkzYqzGmAP3HLuG",
|
'hgSIwDAKvz8PJfkj6xkzYqzGmAP3HLuG',
|
||||||
"shared",
|
'shared'
|
||||||
],
|
],
|
||||||
WEBSITE_URL: ["http://localhost:3000", "shared"],
|
WEBSITE_URL: ['http://localhost:3000', 'shared'],
|
||||||
STRIPE_SECRET_KEY: ["sk_test_7348oyho4hfq398HIUOH78", "shared"],
|
STRIPE_SECRET_KEY: ['sk_test_7348oyho4hfq398HIUOH78', 'shared']
|
||||||
},
|
},
|
||||||
workspaceId: projectToLogin,
|
workspaceId: projectToLogin,
|
||||||
env: "Development",
|
env: 'Development'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (email) {
|
if (email) {
|
||||||
telemetry.identify(email);
|
telemetry.identify(email);
|
||||||
telemetry.capture("User Logged In");
|
telemetry.capture('User Logged In');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLogin) {
|
if (isLogin) {
|
||||||
router.push("/dashboard/");
|
router.push('/dashboard/');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setErrorLogin(true);
|
setErrorLogin(true);
|
||||||
console.log("Login response not available");
|
console.log('Login response not available');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Something went wrong during authentication");
|
console.log('Something went wrong during authentication');
|
||||||
}
|
}
|
||||||
return true;
|
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
|
* @param {Buffer} src - source buffer
|
||||||
* @returns {String} text - text of buffer
|
* @returns {String} text - text of buffer
|
||||||
*/
|
*/
|
||||||
function parse(src) {
|
function parse(src: Buffer) {
|
||||||
const obj = {};
|
const obj: Record<string, string> = {};
|
||||||
|
|
||||||
// Convert buffer to string
|
// Convert buffer to string
|
||||||
let lines = src.toString();
|
let lines = src.toString();
|
||||||
|
|
||||||
// Convert line breaks to same format
|
// Convert line breaks to same format
|
||||||
lines = lines.replace(/\r\n?/gm, "\n");
|
lines = lines.replace(/\r\n?/gm, '\n');
|
||||||
|
|
||||||
let match;
|
let match;
|
||||||
while ((match = LINE.exec(lines)) != null) {
|
while ((match = LINE.exec(lines)) != null) {
|
||||||
const key = match[1];
|
const key = match[1];
|
||||||
|
|
||||||
// Default undefined or null to empty string
|
// Default undefined or null to empty string
|
||||||
let value = match[2] || "";
|
let value = match[2] || '';
|
||||||
|
|
||||||
// Remove whitespace
|
// Remove whitespace
|
||||||
value = value.trim();
|
value = value.trim();
|
||||||
@@ -29,12 +29,12 @@ function parse(src) {
|
|||||||
const maybeQuote = value[0];
|
const maybeQuote = value[0];
|
||||||
|
|
||||||
// Remove surrounding quotes
|
// Remove surrounding quotes
|
||||||
value = value.replace(/^(['"`])([\s\S]*)\1$/gm, "$2");
|
value = value.replace(/^(['"`])([\s\S]*)\1$/gm, '$2');
|
||||||
|
|
||||||
// Expand newlines if double quoted
|
// Expand newlines if double quoted
|
||||||
if (maybeQuote === '"') {
|
if (maybeQuote === '"') {
|
||||||
value = value.replace(/\\n/g, "\n");
|
value = value.replace(/\\n/g, '\n');
|
||||||
value = value.replace(/\\r/g, "\r");
|
value = value.replace(/\\r/g, '\r');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to object
|
// Add to object
|
||||||
+5
-5
@@ -3,19 +3,19 @@
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const guidGenerator = () => {
|
const guidGenerator = () => {
|
||||||
var S4 = function () {
|
const S4 = function () {
|
||||||
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
|
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
S4() +
|
S4() +
|
||||||
S4() +
|
S4() +
|
||||||
"-" +
|
'-' +
|
||||||
S4() +
|
S4() +
|
||||||
"-" +
|
'-' +
|
||||||
S4() +
|
S4() +
|
||||||
"-" +
|
'-' +
|
||||||
S4() +
|
S4() +
|
||||||
"-" +
|
'-' +
|
||||||
S4() +
|
S4() +
|
||||||
S4() +
|
S4() +
|
||||||
S4()
|
S4()
|
||||||
+37
-26
@@ -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 { envMapping } from '../../../public/data/frequentConstants';
|
||||||
import guidGenerator from "../randomId";
|
import guidGenerator from '../randomId';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
decryptAssymmetric,
|
decryptAssymmetric,
|
||||||
decryptSymmetric,
|
decryptSymmetric
|
||||||
} = require("../cryptography/crypto");
|
} = require('../cryptography/crypto');
|
||||||
const nacl = require("tweetnacl");
|
const nacl = require('tweetnacl');
|
||||||
nacl.util = require("tweetnacl-util");
|
nacl.util = require('tweetnacl-util');
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
env: keyof typeof envMapping;
|
||||||
|
setFileState: any;
|
||||||
|
setIsKeyAvailable: any;
|
||||||
|
setData: any;
|
||||||
|
workspaceId: string;
|
||||||
|
}
|
||||||
|
|
||||||
const getSecretsForProject = async ({
|
const getSecretsForProject = async ({
|
||||||
env,
|
env,
|
||||||
setFileState,
|
setFileState,
|
||||||
setIsKeyAvailable,
|
setIsKeyAvailable,
|
||||||
setData,
|
setData,
|
||||||
workspaceId,
|
workspaceId
|
||||||
}) => {
|
}: Props) => {
|
||||||
try {
|
try {
|
||||||
let file;
|
let file;
|
||||||
try {
|
try {
|
||||||
@@ -24,44 +32,47 @@ const getSecretsForProject = async ({
|
|||||||
|
|
||||||
setFileState(file);
|
setFileState(file);
|
||||||
} catch (error) {
|
} 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
|
// This is called isKeyAvilable but what it really means is if a person is able to create new key pairs
|
||||||
setIsKeyAvailable(
|
setIsKeyAvailable(!file.key ? file.secrets.length == 0 : true);
|
||||||
!file.key ? (file.secrets.length == 0 ? true : false) : 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) {
|
if (file.key) {
|
||||||
// assymmetrically decrypt symmetric key with local private key
|
// assymmetrically decrypt symmetric key with local private key
|
||||||
const key = decryptAssymmetric({
|
const key = decryptAssymmetric({
|
||||||
ciphertext: file.key.encryptedKey,
|
ciphertext: file.key.encryptedKey,
|
||||||
nonce: file.key.nonce,
|
nonce: file.key.nonce,
|
||||||
publicKey: file.key.sender.publicKey,
|
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) => {
|
||||||
|
=======
|
||||||
|
|
||||||
|
file.secrets.map((secretPair: any) => {
|
||||||
|
>>>>>>> 158c51ff3cbcd9a8eab6c44e728232d79a1cbab9:frontend/components/utilities/secrets/getSecretsForProject.ts
|
||||||
// decrypt .env file with symmetric key
|
// decrypt .env file with symmetric key
|
||||||
const plainTextKey = decryptSymmetric({
|
const plainTextKey = decryptSymmetric({
|
||||||
ciphertext: secretPair.secretKey.ciphertext,
|
ciphertext: secretPair.secretKey.ciphertext,
|
||||||
iv: secretPair.secretKey.iv,
|
iv: secretPair.secretKey.iv,
|
||||||
tag: secretPair.secretKey.tag,
|
tag: secretPair.secretKey.tag,
|
||||||
key,
|
key
|
||||||
});
|
});
|
||||||
|
|
||||||
const plainTextValue = decryptSymmetric({
|
const plainTextValue = decryptSymmetric({
|
||||||
ciphertext: secretPair.secretValue.ciphertext,
|
ciphertext: secretPair.secretValue.ciphertext,
|
||||||
iv: secretPair.secretValue.iv,
|
iv: secretPair.secretValue.iv,
|
||||||
tag: secretPair.secretValue.tag,
|
tag: secretPair.secretValue.tag,
|
||||||
key,
|
key
|
||||||
});
|
});
|
||||||
tempFileState.push({
|
tempFileState.push({
|
||||||
key: plainTextKey,
|
key: plainTextKey,
|
||||||
value: plainTextValue,
|
value: plainTextValue,
|
||||||
type: secretPair.type,
|
type: secretPair.type
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -71,9 +82,9 @@ const getSecretsForProject = async ({
|
|||||||
tempFileState.map((line, index) => [
|
tempFileState.map((line, index) => [
|
||||||
guidGenerator(),
|
guidGenerator(),
|
||||||
index,
|
index,
|
||||||
line["key"],
|
line['key'],
|
||||||
line["value"],
|
line['value'],
|
||||||
line["type"],
|
line['type']
|
||||||
])
|
])
|
||||||
// .sort((a, b) =>
|
// .sort((a, b) =>
|
||||||
// sortMethod == "alphabetical"
|
// sortMethod == "alphabetical"
|
||||||
@@ -84,12 +95,12 @@ const getSecretsForProject = async ({
|
|||||||
return tempFileState.map((line, index) => [
|
return tempFileState.map((line, index) => [
|
||||||
guidGenerator(),
|
guidGenerator(),
|
||||||
index,
|
index,
|
||||||
line["key"],
|
line['key'],
|
||||||
line["value"],
|
line['value'],
|
||||||
line["type"],
|
line['type']
|
||||||
]);
|
]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Something went wrong during accessing or decripting secrets.");
|
console.log('Something went wrong during accessing or decripting secrets.');
|
||||||
}
|
}
|
||||||
return true;
|
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;
|
||||||
+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)
|
* This is the second step of the change password process (pake)
|
||||||
@@ -11,12 +20,12 @@ const changePassword2 = ({
|
|||||||
tag,
|
tag,
|
||||||
salt,
|
salt,
|
||||||
verifier,
|
verifier,
|
||||||
clientProof,
|
clientProof
|
||||||
}) => {
|
}: Props) => {
|
||||||
return SecurityClient.fetchCall("/api/v1/password/change-password", {
|
return SecurityClient.fetchCall('/api/v1/password/change-password', {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
clientProof: clientProof,
|
clientProof: clientProof,
|
||||||
@@ -24,13 +33,13 @@ const changePassword2 = ({
|
|||||||
iv: iv,
|
iv: iv,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
salt: salt,
|
salt: salt,
|
||||||
verifier: verifier,
|
verifier: verifier
|
||||||
}),
|
})
|
||||||
}).then(async (res) => {
|
}).then(async (res) => {
|
||||||
if (res.status == 200) {
|
if (res && res.status == 200) {
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
console.log("Failed to change the password");
|
console.log('Failed to change the password');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import SecurityClient from "~/utilities/SecurityClient.js";
|
import SecurityClient from '~/utilities/SecurityClient';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is used to check if the user is authenticated.
|
* This function is used to check if the user is authenticated.
|
||||||
@@ -7,17 +7,17 @@ import SecurityClient from "~/utilities/SecurityClient.js";
|
|||||||
* @param {*} res
|
* @param {*} res
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const checkAuth = async (req, res) => {
|
const checkAuth = async () => {
|
||||||
return SecurityClient.fetchCall("/api/v1/auth/checkAuth", {
|
return SecurityClient.fetchCall('/api/v1/auth/checkAuth', {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json'
|
||||||
},
|
}
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
if (res.status == 200) {
|
if (res && res.status == 200) {
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
console.log("Not authorized");
|
console.log('Not authorized');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
+11
-6
@@ -1,19 +1,24 @@
|
|||||||
|
interface Props {
|
||||||
|
email: string;
|
||||||
|
code: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This route check the verification code from the email that user just recieved
|
* This route check the verification code from the email that user just recieved
|
||||||
* @param {*} email
|
* @param {*} email
|
||||||
* @param {*} code
|
* @param {*} code
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const checkEmailVerificationCode = (email, code) => {
|
const checkEmailVerificationCode = ({ email, code }: Props) => {
|
||||||
return fetch("/api/v1/signup/email/verify", {
|
return fetch('/api/v1/signup/email/verify', {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
email: email,
|
email: email,
|
||||||
code: code,
|
code: code
|
||||||
}),
|
})
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
+22
-8
@@ -1,3 +1,17 @@
|
|||||||
|
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.
|
* This function is called in the end of the signup process.
|
||||||
* It sends all the necessary nformation to the server.
|
* It sends all the necessary nformation to the server.
|
||||||
@@ -24,13 +38,13 @@ const completeAccountInformationSignup = ({
|
|||||||
tag,
|
tag,
|
||||||
salt,
|
salt,
|
||||||
verifier,
|
verifier,
|
||||||
token,
|
token
|
||||||
}) => {
|
}: Props) => {
|
||||||
return fetch("/api/v1/signup/complete-account/signup", {
|
return fetch('/api/v1/signup/complete-account/signup', {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: "Bearer " + token,
|
Authorization: 'Bearer ' + token
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
email,
|
email,
|
||||||
@@ -42,8 +56,8 @@ const completeAccountInformationSignup = ({
|
|||||||
iv,
|
iv,
|
||||||
tag,
|
tag,
|
||||||
salt,
|
salt,
|
||||||
verifier,
|
verifier
|
||||||
}),
|
})
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
+21
-8
@@ -1,3 +1,16 @@
|
|||||||
|
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.
|
* This function is called in the end of the signup process.
|
||||||
* It sends all the necessary nformation to the server.
|
* It sends all the necessary nformation to the server.
|
||||||
@@ -22,13 +35,13 @@ const completeAccountInformationSignupInvite = ({
|
|||||||
tag,
|
tag,
|
||||||
salt,
|
salt,
|
||||||
verifier,
|
verifier,
|
||||||
token,
|
token
|
||||||
}) => {
|
}: Props) => {
|
||||||
return fetch("/api/v1/signup/complete-account/invite", {
|
return fetch('/api/v1/signup/complete-account/invite', {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json',
|
||||||
Authorization: "Bearer " + token,
|
Authorization: 'Bearer ' + token
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
email: email,
|
email: email,
|
||||||
@@ -39,8 +52,8 @@ const completeAccountInformationSignupInvite = ({
|
|||||||
iv: iv,
|
iv: iv,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
salt: salt,
|
salt: salt,
|
||||||
verifier: verifier,
|
verifier: verifier
|
||||||
}),
|
})
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -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,44 @@
|
|||||||
|
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
|
||||||
|
*/
|
||||||
|
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.
|
* 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
|
* We first try to log out - if the authorization fails (response.status = 401), we refetch the new token, and then retry
|
||||||
*/
|
*/
|
||||||
const logout = async () => {
|
const logout = async () => {
|
||||||
return SecurityClient.fetchCall("/api/v1/auth/logout", {
|
return SecurityClient.fetchCall('/api/v1/auth/logout', {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
credentials: "include",
|
credentials: 'include'
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
if (res?.status == 200) {
|
if (res?.status == 200) {
|
||||||
SecurityClient.setToken("");
|
SecurityClient.setToken('');
|
||||||
// Delete the cookie by not setting a value; Alternatively clear the local storage
|
// Delete the cookie by not setting a value; Alternatively clear the local storage
|
||||||
localStorage.setItem("publicKey", "");
|
localStorage.setItem('publicKey', '');
|
||||||
localStorage.setItem("encryptedPrivateKey", "");
|
localStorage.setItem('encryptedPrivateKey', '');
|
||||||
localStorage.setItem("iv", "");
|
localStorage.setItem('iv', '');
|
||||||
localStorage.setItem("tag", "");
|
localStorage.setItem('tag', '');
|
||||||
localStorage.setItem("PRIVATE_KEY", "");
|
localStorage.setItem('PRIVATE_KEY', '');
|
||||||
console.log("User logged out", res);
|
console.log('User logged out', res);
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} 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 {*} 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)
|
* This route send the verification email to the user's email (contains a 6-digit verification code)
|
||||||
* @param {*} email
|
* @param {*} email
|
||||||
*/
|
*/
|
||||||
const sendVerificationEmail = (email) => {
|
const sendVerificationEmail = (email: string) => {
|
||||||
fetch("/api/v1/signup/email/signup", {
|
fetch('/api/v1/signup/email/signup', {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
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,25 @@
|
|||||||
|
interface Props {
|
||||||
|
email: string;
|
||||||
|
code: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This route verifies the signup invite link
|
||||||
|
* @param {*} email
|
||||||
|
* @param {*} code
|
||||||
|
* @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,4 +1,4 @@
|
|||||||
import SecurityClient from "~/utilities/SecurityClient.js";
|
import SecurityClient from '~/utilities/SecurityClient';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function fetches the encrypted secrets from the .env file
|
* This function fetches the encrypted secrets from the .env file
|
||||||
@@ -6,26 +6,26 @@ import SecurityClient from "~/utilities/SecurityClient.js";
|
|||||||
* @param {*} env
|
* @param {*} env
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const getSecrets = async (workspaceId, env) => {
|
const getSecrets = async (workspaceId: string, env: string) => {
|
||||||
return SecurityClient.fetchCall(
|
return SecurityClient.fetchCall(
|
||||||
"/api/v1/secret/" +
|
'/api/v1/secret/' +
|
||||||
workspaceId +
|
workspaceId +
|
||||||
"?" +
|
'?' +
|
||||||
new URLSearchParams({
|
new URLSearchParams({
|
||||||
environment: env,
|
environment: env,
|
||||||
channel: "web",
|
channel: 'web'
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json'
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
).then(async (res) => {
|
).then(async (res) => {
|
||||||
if (res.status == 200) {
|
if (res && res.status == 200) {
|
||||||
return await res.json();
|
return await res.json();
|
||||||
} else {
|
} else {
|
||||||
console.log("Failed to get project secrets");
|
console.log('Failed to get project secrets');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -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,42 @@
|
|||||||
|
import SecurityClient from '~/utilities/SecurityClient';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
workspaceId: string;
|
||||||
|
secrets: any;
|
||||||
|
keys: string;
|
||||||
|
environment: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function uploads the encrypted .env file
|
||||||
|
* @param {*} req
|
||||||
|
* @param {*} res
|
||||||
|
* @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;
|
||||||
@@ -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,33 @@
|
|||||||
|
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 {*} clientPublicKey
|
||||||
|
* @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
|
* This route lets us get info about a certain org
|
||||||
* @param {string} orgId - the organization ID
|
* @param {string} orgId - the organization ID
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const getOrganization = ({ orgId }: { orgId: string; }) => {
|
const getOrganization = ({ orgId }: { orgId: string }) => {
|
||||||
return SecurityClient.fetchCall("/api/v1/organization/" + orgId, {
|
return SecurityClient.fetchCall('/api/v1/organization/' + orgId, {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json'
|
||||||
},
|
}
|
||||||
}).then(async (res) => {
|
}).then(async (res) => {
|
||||||
if (res?.status == 200) {
|
if (res?.status == 200) {
|
||||||
return (await res.json()).organization;
|
return (await res.json()).organization;
|
||||||
} else {
|
} 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.
|
* 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
|
* @param {string} obj.orgId - organization Id
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const getOrganizationUsers = ({ orgId }: { orgId: string; }) => {
|
const getOrganizationUsers = ({ orgId }: { orgId: string }) => {
|
||||||
return SecurityClient.fetchCall(
|
return SecurityClient.fetchCall('/api/v1/organization/' + orgId + '/users', {
|
||||||
"/api/v1/organization/" + orgId + "/users",
|
method: 'GET',
|
||||||
{
|
headers: {
|
||||||
method: "GET",
|
'Content-Type': 'application/json'
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
).then(async (res) => {
|
}).then(async (res) => {
|
||||||
if (res?.status == 200) {
|
if (res?.status == 200) {
|
||||||
return (await res.json()).users;
|
return (await res.json()).users;
|
||||||
} else {
|
} 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.
|
* This route lets us get the all the orgs of a certain user.
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const getOrganizations = () => {
|
const getOrganizations = () => {
|
||||||
return SecurityClient.fetchCall("/api/v1/organization", {
|
return SecurityClient.fetchCall('/api/v1/organization', {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json'
|
||||||
},
|
}
|
||||||
}).then(async (res) => {
|
}).then(async (res) => {
|
||||||
if (res?.status == 200) {
|
if (res?.status == 200) {
|
||||||
return (await res.json()).organizations;
|
return (await res.json()).organizations;
|
||||||
} else {
|
} 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
|
* This route gets service tokens for a specific user in a project
|
||||||
@@ -12,12 +22,12 @@ const addServiceToken = ({
|
|||||||
expiresIn,
|
expiresIn,
|
||||||
publicKey,
|
publicKey,
|
||||||
encryptedKey,
|
encryptedKey,
|
||||||
nonce,
|
nonce
|
||||||
}) => {
|
}: Props) => {
|
||||||
return SecurityClient.fetchCall("/api/v1/service-token/", {
|
return SecurityClient.fetchCall('/api/v1/service-token/', {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
name,
|
name,
|
||||||
@@ -26,13 +36,13 @@ const addServiceToken = ({
|
|||||||
expiresIn,
|
expiresIn,
|
||||||
publicKey,
|
publicKey,
|
||||||
encryptedKey,
|
encryptedKey,
|
||||||
nonce,
|
nonce
|
||||||
}),
|
})
|
||||||
}).then(async (res) => {
|
}).then(async (res) => {
|
||||||
if (res.status == 200) {
|
if (res && res.status == 200) {
|
||||||
return (await res.json()).token;
|
return (await res.json()).token;
|
||||||
} else {
|
} 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.
|
* This route gets the information about a specific user.
|
||||||
*/
|
*/
|
||||||
const getUser = () => {
|
const getUser = () => {
|
||||||
return SecurityClient.fetchCall("/api/v1/user", {
|
return SecurityClient.fetchCall('/api/v1/user', {
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json'
|
||||||
},
|
}
|
||||||
}).then(async (res) => {
|
}).then(async (res) => {
|
||||||
if (res?.status == 200) {
|
if (res?.status == 200) {
|
||||||
return (await res.json()).user;
|
return (await res.json()).user;
|
||||||
} else {
|
} 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
|
* This route registers a certain action for a user
|
||||||
@@ -6,24 +6,24 @@ import SecurityClient from "~/utilities/SecurityClient";
|
|||||||
* @param {*} workspaceId
|
* @param {*} workspaceId
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const checkUserAction = ({ action }) => {
|
const checkUserAction = ({ action }: { action: string }) => {
|
||||||
return SecurityClient.fetchCall(
|
return SecurityClient.fetchCall(
|
||||||
"/api/v1/user-action" +
|
'/api/v1/user-action' +
|
||||||
"?" +
|
'?' +
|
||||||
new URLSearchParams({
|
new URLSearchParams({
|
||||||
action,
|
action
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json'
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
).then(async (res) => {
|
).then(async (res) => {
|
||||||
if (res.status == 200) {
|
if (res && res.status == 200) {
|
||||||
return (await res.json()).userAction;
|
return (await res.json()).userAction;
|
||||||
} else {
|
} 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.
|
* 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
|
* @param {string} organizationId - org ID
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const createWorkspace = ( { workspaceName, organizationId }: { workspaceName: string; organizationId: string; }) => {
|
const createWorkspace = ({
|
||||||
return SecurityClient.fetchCall("/api/v1/workspace", {
|
workspaceName,
|
||||||
method: "POST",
|
organizationId
|
||||||
|
}: {
|
||||||
|
workspaceName: string;
|
||||||
|
organizationId: string;
|
||||||
|
}) => {
|
||||||
|
return SecurityClient.fetchCall('/api/v1/workspace', {
|
||||||
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
workspaceName: workspaceName,
|
workspaceName: workspaceName,
|
||||||
organizationId: organizationId,
|
organizationId: organizationId
|
||||||
}),
|
})
|
||||||
}).then(async (res) => {
|
}).then(async (res) => {
|
||||||
if (res?.status == 200) {
|
if (res?.status == 200) {
|
||||||
return (await res.json()).workspace;
|
return (await res.json()).workspace;
|
||||||
} else {
|
} 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
|
* Get the latest key pairs from a certain workspace
|
||||||
* @param {string} workspaceId
|
* @param {string} workspaceId
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const getLatestFileKey = ({ workspaceId } : { workspaceId: string; }) => {
|
const getLatestFileKey = ({ workspaceId }: { workspaceId: string }) => {
|
||||||
return SecurityClient.fetchCall(
|
return SecurityClient.fetchCall('/api/v1/key/' + workspaceId + '/latest', {
|
||||||
"/api/v1/key/" + workspaceId + "/latest",
|
method: 'GET',
|
||||||
{
|
headers: {
|
||||||
method: "GET",
|
'Content-Type': 'application/json'
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
).then(async (res) => {
|
}).then(async (res) => {
|
||||||
if (res?.status == 200) {
|
if (res?.status == 200) {
|
||||||
return await res.json();
|
return await res.json();
|
||||||
} else {
|
} 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.
|
* This route lets us get the information of a certain project.
|
||||||
* @param {*} projectId - project ID (we renamed workspaces to projects in the app)
|
* @param {*} projectId - project ID (we renamed workspaces to projects in the app)
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const getProjectInfo = ({ projectId }: { projectId: string; }) => {
|
const getProjectInfo = ({ projectId }: { projectId: string }) => {
|
||||||
return SecurityClient.fetchCall(
|
return SecurityClient.fetchCall('/api/v1/workspace/' + projectId, {
|
||||||
"/api/v1/workspace/" + projectId,
|
method: 'GET',
|
||||||
{
|
headers: {
|
||||||
method: "GET",
|
'Content-Type': 'application/json'
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
).then(async (res) => {
|
}).then(async (res) => {
|
||||||
if (res?.status == 200) {
|
if (res?.status == 200) {
|
||||||
return (await res.json()).workspace;
|
return (await res.json()).workspace;
|
||||||
} else {
|
} 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.
|
* This route lets us get all the users in the workspace.
|
||||||
* @param {string} workspaceId - workspace ID
|
* @param {string} workspaceId - workspace ID
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const getWorkspaceUsers = ({ workspaceId }: { workspaceId: string; }) => {
|
const getWorkspaceUsers = ({ workspaceId }: { workspaceId: string }) => {
|
||||||
return SecurityClient.fetchCall(
|
return SecurityClient.fetchCall(
|
||||||
"/api/v1/workspace/" + workspaceId + "/users",
|
'/api/v1/workspace/' + workspaceId + '/users',
|
||||||
{
|
{
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json'
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
).then(async (res) => {
|
).then(async (res) => {
|
||||||
if (res?.status == 200) {
|
if (res?.status == 200) {
|
||||||
return (await res.json()).users;
|
return (await res.json()).users;
|
||||||
} else {
|
} else {
|
||||||
console.log("Failed to get Project Users");
|
console.log('Failed to get Project Users');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user