mirror of
https://github.com/Infisical/infisical.git
synced 2025-03-29 22:02:57 +00:00
Refactoring functions into services, helper functions, hooks, patch bugs
This commit is contained in:
backend/src
docs/integrations
frontend
public/locales
src
components
login
navigation
signup
utilities
config
hooks/api/auth
layouts/AppLayout
pages
api/auth
CompleteAccountInformationSignup.tsCompleteAccountInformationSignupInvite.tsLogout.tsresendMfaToken.tsverifyMfaToken.ts
login.tsxsignup.tsxsignupinvite.tsx@ -269,19 +269,36 @@ export const verifyMfaToken = async (req: Request, res: Response) => {
|
||||
secure: NODE_ENV === 'production' ? true : false
|
||||
});
|
||||
|
||||
interface VerifyMfaTokenRes {
|
||||
encryptionVersion: number;
|
||||
protectedKey?: string;
|
||||
protectedKeyIV?: string;
|
||||
protectedKeyTag?: string;
|
||||
token: string;
|
||||
publicKey: string;
|
||||
encryptedPrivateKey: string;
|
||||
iv: string;
|
||||
tag: string;
|
||||
}
|
||||
|
||||
const resObj: VerifyMfaTokenRes = {
|
||||
encryptionVersion: user.encryptionVersion,
|
||||
token: tokens.token,
|
||||
publicKey: user.publicKey as string,
|
||||
encryptedPrivateKey: user.encryptedPrivateKey as string,
|
||||
iv: user.iv as string,
|
||||
tag: user.tag as string
|
||||
}
|
||||
|
||||
if (user?.protectedKey && user?.protectedKeyIV && user?.protectedKeyTag) {
|
||||
resObj.protectedKey = user.protectedKey;
|
||||
resObj.protectedKeyIV = user.protectedKeyIV;
|
||||
resObj.protectedKeyTag = user.protectedKeyTag;
|
||||
}
|
||||
|
||||
// case: user does not have MFA enabled
|
||||
// return (access) token in response
|
||||
return res.status(200).send({
|
||||
encryptionVersion: user.encryptionVersion,
|
||||
protectedKey: user.protectedKey ?? null,
|
||||
protectedKeyIV: user.protectedKeyIV ?? null,
|
||||
protectedKeyTag: user.protectedKeyTag ?? null,
|
||||
token: tokens.token,
|
||||
publicKey: user.publicKey,
|
||||
encryptedPrivateKey: user.encryptedPrivateKey,
|
||||
iv: user.iv,
|
||||
tag: user.tag
|
||||
});
|
||||
return res.status(200).send(resObj);
|
||||
} catch (err) {
|
||||
Sentry.setUser(null);
|
||||
Sentry.captureException(err);
|
||||
|
@ -7,6 +7,7 @@ import {
|
||||
} from '../../helpers/signup';
|
||||
import { issueAuthTokens } from '../../helpers/auth';
|
||||
import { INVITED, ACCEPTED } from '../../variables';
|
||||
import { NODE_ENV } from '../../config';
|
||||
import axios from 'axios';
|
||||
|
||||
/**
|
||||
@ -105,7 +106,6 @@ export const completeAccountSignup = async (req: Request, res: Response) => {
|
||||
});
|
||||
|
||||
token = tokens.token;
|
||||
refreshToken = tokens.refreshToken;
|
||||
|
||||
// sending a welcome email to new users
|
||||
if (process.env.LOOPS_API_KEY) {
|
||||
@ -121,6 +121,14 @@ export const completeAccountSignup = async (req: Request, res: Response) => {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// store (refresh) token in httpOnly cookie
|
||||
res.cookie('jid', tokens.refreshToken, {
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
sameSite: 'strict',
|
||||
secure: NODE_ENV === 'production' ? true : false
|
||||
});
|
||||
} catch (err) {
|
||||
Sentry.setUser(null);
|
||||
Sentry.captureException(err);
|
||||
@ -132,8 +140,7 @@ export const completeAccountSignup = async (req: Request, res: Response) => {
|
||||
return res.status(200).send({
|
||||
message: 'Successfully set up account',
|
||||
user,
|
||||
token,
|
||||
refreshToken
|
||||
token
|
||||
});
|
||||
};
|
||||
|
||||
@ -219,7 +226,14 @@ export const completeAccountInvite = async (req: Request, res: Response) => {
|
||||
});
|
||||
|
||||
token = tokens.token;
|
||||
refreshToken = tokens.refreshToken;
|
||||
|
||||
// store (refresh) token in httpOnly cookie
|
||||
res.cookie('jid', tokens.refreshToken, {
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
sameSite: 'strict',
|
||||
secure: NODE_ENV === 'production' ? true : false
|
||||
});
|
||||
} catch (err) {
|
||||
Sentry.setUser(null);
|
||||
Sentry.captureException(err);
|
||||
@ -227,11 +241,10 @@ export const completeAccountInvite = async (req: Request, res: Response) => {
|
||||
message: 'Failed to complete account setup'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return res.status(200).send({
|
||||
message: 'Successfully set up account',
|
||||
user,
|
||||
token,
|
||||
refreshToken
|
||||
token
|
||||
});
|
||||
};
|
@ -12,7 +12,7 @@ import {
|
||||
import {
|
||||
SALT_ROUNDS
|
||||
} from '../config';
|
||||
import { UnauthorizedRequestError } from '../utils/errors';
|
||||
import { ForbiddenRequestError } from '../utils/errors';
|
||||
|
||||
/**
|
||||
* Create and store a token in the database for purpose [type]
|
||||
@ -65,29 +65,45 @@ const createTokenHelper = async ({
|
||||
break;
|
||||
}
|
||||
|
||||
interface Query {
|
||||
interface TokenDataQuery {
|
||||
type: string;
|
||||
email?: string;
|
||||
phoneNumber?: string;
|
||||
organization?: Types.ObjectId;
|
||||
}
|
||||
|
||||
interface TokenDataUpdate {
|
||||
type: string;
|
||||
email?: string;
|
||||
phoneNumber?: string;
|
||||
organization?: Types.ObjectId;
|
||||
tokenHash: string;
|
||||
expiresAt: Date;
|
||||
}
|
||||
|
||||
const query: Query = { type };
|
||||
const query: TokenDataQuery = { type };
|
||||
const update: TokenDataUpdate = {
|
||||
type,
|
||||
tokenHash: await bcrypt.hash(token, SALT_ROUNDS),
|
||||
expiresAt
|
||||
}
|
||||
|
||||
if (email) { query.email = email; }
|
||||
if (phoneNumber) { query.phoneNumber = phoneNumber; }
|
||||
if (organizationId) { query.organization = organizationId }
|
||||
if (email) {
|
||||
query.email = email;
|
||||
update.email = email;
|
||||
}
|
||||
if (phoneNumber) {
|
||||
query.phoneNumber = phoneNumber;
|
||||
update.phoneNumber = phoneNumber;
|
||||
}
|
||||
if (organizationId) {
|
||||
query.organization = organizationId
|
||||
update.organization = organizationId
|
||||
}
|
||||
|
||||
await TokenData.findOneAndUpdate(
|
||||
query,
|
||||
{
|
||||
type,
|
||||
email,
|
||||
phoneNumber,
|
||||
organization: organizationId,
|
||||
tokenHash: await bcrypt.hash(token, SALT_ROUNDS),
|
||||
expiresAt
|
||||
},
|
||||
update,
|
||||
{
|
||||
new: true,
|
||||
upsert: true
|
||||
@ -123,37 +139,38 @@ const validateTokenHelper = async ({
|
||||
organizationId?: Types.ObjectId;
|
||||
token: string;
|
||||
}) => {
|
||||
try {
|
||||
interface Query {
|
||||
type: string;
|
||||
email?: string;
|
||||
phoneNumber?: string;
|
||||
organization?: Types.ObjectId;
|
||||
}
|
||||
interface Query {
|
||||
type: string;
|
||||
email?: string;
|
||||
phoneNumber?: string;
|
||||
organization?: Types.ObjectId;
|
||||
}
|
||||
|
||||
const query: Query = { type };
|
||||
const query: Query = { type };
|
||||
|
||||
if (email) { query.email = email; }
|
||||
if (phoneNumber) { query.phoneNumber = phoneNumber; }
|
||||
if (organizationId) { query.organization = organizationId; }
|
||||
if (email) { query.email = email; }
|
||||
if (phoneNumber) { query.phoneNumber = phoneNumber; }
|
||||
if (organizationId) { query.organization = organizationId; }
|
||||
|
||||
const tokenData = await TokenData.findOneAndDelete(query);
|
||||
|
||||
if (!tokenData) throw new Error('Failed to find token to validate');
|
||||
|
||||
if (tokenData.expiresAt < new Date()) throw new Error('Token has expired');
|
||||
|
||||
const isValid = await bcrypt.compare(token, tokenData.tokenHash);
|
||||
if (!isValid) throw UnauthorizedRequestError({
|
||||
const tokenData = await TokenData.findOne(query).select('+tokenHash');
|
||||
|
||||
if (!tokenData) throw new Error('Failed to find token to validate');
|
||||
|
||||
if (tokenData.expiresAt < new Date()) {
|
||||
await TokenData.findByIdAndDelete(tokenData._id);
|
||||
throw ForbiddenRequestError({
|
||||
message: 'Failed token data validation due to token is no longer valid'
|
||||
});
|
||||
}
|
||||
|
||||
const isValid = await bcrypt.compare(token, tokenData.tokenHash);
|
||||
if (!isValid) {
|
||||
throw ForbiddenRequestError({
|
||||
message: 'Failed token data validation due to incorrect token'
|
||||
});
|
||||
} catch (err) {
|
||||
Sentry.setUser(null);
|
||||
Sentry.captureException(err);
|
||||
throw new Error(
|
||||
"Failed to validate token data"
|
||||
);
|
||||
}
|
||||
|
||||
await TokenData.findByIdAndDelete(tokenData._id);
|
||||
}
|
||||
|
||||
export {
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { ErrorRequestHandler } from "express";
|
||||
|
||||
import * as Sentry from '@sentry/node';
|
||||
import { InternalServerError } from "../utils/errors";
|
||||
import { InternalServerError, UnauthorizedRequestError } from "../utils/errors";
|
||||
import { getLogger } from "../utils/logger";
|
||||
import RequestError, { LogLevel } from "../utils/requestError";
|
||||
import { NODE_ENV } from "../config";
|
||||
|
||||
import { TokenExpiredError } from 'jsonwebtoken';
|
||||
|
||||
export const requestErrorHandler: ErrorRequestHandler = (error: RequestError | Error, req, res, next) => {
|
||||
if (res.headersSent) return next();
|
||||
@ -16,7 +17,9 @@ export const requestErrorHandler: ErrorRequestHandler = (error: RequestError | E
|
||||
}
|
||||
|
||||
//TODO: Find better way to type check for error. In current setting you need to cast type to get the functions and variables from RequestError
|
||||
if (!(error instanceof RequestError)) {
|
||||
if (error instanceof TokenExpiredError) {
|
||||
error = UnauthorizedRequestError({ stack: error.stack, message: 'Token expired' });
|
||||
} else if (!(error instanceof RequestError)) {
|
||||
error = InternalServerError({ context: { exception: error.message }, stack: error.stack })
|
||||
getLogger('backend-main').log((<RequestError>error).levelName.toLowerCase(), (<RequestError>error).message)
|
||||
}
|
||||
|
@ -1,5 +1,37 @@
|
||||
---
|
||||
title: "Circle CI"
|
||||
description: "How to automatically sync secrets from Infisical into your CircleCI project."
|
||||
---
|
||||
|
||||
Coming soon.
|
||||
Prerequisites:
|
||||
|
||||
- Set up and add envars to [Infisical Cloud](https://app.infisical.com)
|
||||
|
||||
## Navigate to your project's integrations tab
|
||||
|
||||

|
||||
|
||||
## Authorize Infisical for CircleCI
|
||||
|
||||
Obtain a Fly.io access token in Access Tokens
|
||||
|
||||

|
||||

|
||||
|
||||
Press on the Fly.io tile and input your Fly.io access token to grant Infisical access to your Fly.io account.
|
||||
|
||||

|
||||
|
||||
<Info>
|
||||
If this is your project's first cloud integration, then you'll have to grant
|
||||
Infisical access to your project's environment variables. Although this step
|
||||
breaks E2EE, it's necessary for Infisical to sync the environment variables to
|
||||
the cloud platform.
|
||||
</Info>
|
||||
|
||||
## Start integration
|
||||
|
||||
Select which Infisical environment secrets you want to sync to which Fly.io app and press create integration to start syncing secrets to Fly.io.
|
||||
|
||||

|
||||

|
||||
|
@ -21,6 +21,8 @@ Missing an integration? Throw in a [request](https://github.com/Infisical/infisi
|
||||
| [AWS Parameter Store](/integrations/cloud/aws-parameter-store) | Cloud | Available |
|
||||
| [AWS Secret Manager](/integrations/cloud/aws-secret-manager) | Cloud | Available |
|
||||
| [GitHub Actions](/integrations/cicd/githubactions) | CI/CD | Available |
|
||||
| [GitLab Pipeline](/integrations/cicd/gitlab) | CI/CD | Available |
|
||||
| [CircleCI](/integrations/cicd/circleci) | CI/CD | Available |
|
||||
| [React](/integrations/frameworks/react) | Framework | Available |
|
||||
| [Vue](/integrations/frameworks/vue) | Framework | Available |
|
||||
| [Express](/integrations/frameworks/express) | Framework | Available |
|
||||
@ -39,8 +41,6 @@ Missing an integration? Throw in a [request](https://github.com/Infisical/infisi
|
||||
| GCP | Cloud | Coming soon |
|
||||
| Azure | Cloud | Coming soon |
|
||||
| DigitalOcean | Cloud | Coming soon |
|
||||
| [GitLab Pipeline](/integrations/cicd/gitlab) | CI/CD | Available |
|
||||
| [CircleCI](/integrations/cicd/circleci) | CI/CD | Coming soon |
|
||||
| TravisCI | CI/CD | Coming soon |
|
||||
| GitHub Actions | CI/CD | Coming soon |
|
||||
| Jenkins | CI/CD | Coming soon |
|
||||
|
@ -9,9 +9,9 @@
|
||||
"step1-start": "Let's get started",
|
||||
"step1-privacy": "By creating an account, you agree to our Terms and have read and acknowledged the Privacy Policy.",
|
||||
"step1-submit": "Get Started",
|
||||
"step2-message": "We've sent a verification email to",
|
||||
"step2-message": "We've sent a verification code to",
|
||||
"step2-code-error": "Oops. Your code is wrong. Please try again.",
|
||||
"step2-resend-alert": "Don't see the email?",
|
||||
"step2-resend-alert": "Don't see the code?",
|
||||
"step2-resend-submit": "Resend",
|
||||
"step2-resend-progress": "Resending...",
|
||||
"step2-spam-alert": "Make sure to check your spam inbox.",
|
||||
|
@ -11,7 +11,7 @@
|
||||
"step1-submit": "C'est parti",
|
||||
"step2-message": "Nous avons envoyé un email de vérification à",
|
||||
"step2-code-error": "Oops. Votre code est faux. Veuillez réessayer.",
|
||||
"step2-resend-alert": "Vous ne voyez pas l'email?",
|
||||
"step2-resend-alert": "Vous ne voyez pas le code?",
|
||||
"step2-resend-submit": "Renvoyer",
|
||||
"step2-resend-progress": "Envoie en cours...",
|
||||
"step2-spam-alert": "Assurez-vous de vérifier vos spams.",
|
||||
|
@ -11,7 +11,7 @@
|
||||
"step1-submit": "Başla",
|
||||
"step2-message": "Şu adrese bir doğrulama maili yolladık",
|
||||
"step2-code-error": "Tüh. Kodun hatalı. Lütfen tekrar dene.",
|
||||
"step2-resend-alert": "Mail ulaşamadı mı?",
|
||||
"step2-resend-alert": "Kodu ulaşamadı mı?",
|
||||
"step2-resend-submit": "Tekrar Yolla",
|
||||
"step2-resend-progress": "Tekrar yollanıyor...",
|
||||
"step2-spam-alert": "Spam kutunuzu kontrol ettiğinizden emin olun.",
|
||||
|
@ -5,7 +5,7 @@ import { useRouter } from 'next/router';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
import attemptLoginMfa from '@app/components/utilities/attemptLoginMfa';
|
||||
import resendMfaToken from '@app/pages/api/auth/resendMfaToken';
|
||||
import { useSendMfaToken } from '@app/hooks/api/auth';
|
||||
|
||||
import Button from '../basic/buttons/Button';
|
||||
import Error from '../basic/Error';
|
||||
@ -50,6 +50,8 @@ export default function MFAStep({
|
||||
const [mfaCode, setMfaCode] = useState('');
|
||||
const [codeError, setCodeError] = useState(false);
|
||||
|
||||
const sendMfaToken = useSendMfaToken();
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleLoginMfa = async () => {
|
||||
@ -72,15 +74,14 @@ export default function MFAStep({
|
||||
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
setIsLoading(false);
|
||||
setCodeError(true);
|
||||
}
|
||||
}
|
||||
|
||||
const handleResendMfaCode = async () => {
|
||||
try {
|
||||
await resendMfaToken({
|
||||
email
|
||||
});
|
||||
await sendMfaToken.mutateAsync({ email });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
@ -87,7 +87,6 @@ export default function Navbar() {
|
||||
}, []);
|
||||
|
||||
const closeApp = async () => {
|
||||
console.log('Logging out...');
|
||||
await logout();
|
||||
router.push('/login');
|
||||
};
|
||||
|
@ -161,6 +161,8 @@ export default function UserInfoStep({
|
||||
organizationName: `${firstName}'s organization`
|
||||
});
|
||||
|
||||
// unset signup JWT token and set JWT token
|
||||
SecurityClient.setSignupToken('');
|
||||
SecurityClient.setToken(response.token);
|
||||
|
||||
saveTokenToLocalStorage({
|
||||
@ -174,14 +176,18 @@ export default function UserInfoStep({
|
||||
privateKey
|
||||
});
|
||||
|
||||
incrementStep();
|
||||
|
||||
const userOrgs = await getOrganizations();
|
||||
await ProjectService.initProject({
|
||||
organizationId: userOrgs[0]?._id,
|
||||
const orgId = userOrgs[0]?._id;
|
||||
const project = await ProjectService.initProject({
|
||||
organizationId: orgId,
|
||||
projectName: 'Example Project'
|
||||
});
|
||||
|
||||
localStorage.setItem('orgData.id', orgId);
|
||||
localStorage.setItem('projectData.id', project._id);
|
||||
|
||||
incrementStep();
|
||||
|
||||
} catch (error) {
|
||||
setIsLoading(false);
|
||||
console.error(error);
|
||||
|
@ -1,7 +1,15 @@
|
||||
import { getAuthToken, setAuthToken , setMfaTempToken } from '@app/reactQuery';
|
||||
import {
|
||||
getAuthToken,
|
||||
setAuthToken,
|
||||
setMfaTempToken,
|
||||
setSignupTempToken} from '@app/reactQuery';
|
||||
|
||||
// depreciated: go for apiRequest module in config/api
|
||||
export default class SecurityClient {
|
||||
static setSignupToken(tokenStr: string) {
|
||||
setSignupTempToken(tokenStr);
|
||||
}
|
||||
|
||||
static setMfaToken(tokenStr: string) {
|
||||
setMfaTempToken(tokenStr);
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ const attemptLogin = async (
|
||||
client.setSalt(salt);
|
||||
client.setServerPublicKey(serverPublicKey);
|
||||
const clientProof = client.getProof(); // called M1
|
||||
|
||||
|
||||
const {
|
||||
mfaEnabled,
|
||||
encryptionVersion,
|
||||
@ -65,7 +65,7 @@ const attemptLogin = async (
|
||||
// case: MFA is enabled
|
||||
|
||||
// set temporary (MFA) JWT token
|
||||
SecurityClient.setToken(token);
|
||||
SecurityClient.setMfaToken(token);
|
||||
|
||||
resolve({
|
||||
mfaEnabled,
|
||||
@ -113,40 +113,14 @@ const attemptLogin = async (
|
||||
const userOrgs = await getOrganizations();
|
||||
const orgId = userOrgs[0]._id;
|
||||
localStorage.setItem('orgData.id', orgId);
|
||||
|
||||
|
||||
const orgUserProjects = await getOrganizationUserProjects({
|
||||
orgId
|
||||
});
|
||||
localStorage.setItem('projectData.id', orgUserProjects[0]._id);
|
||||
|
||||
// // TODO: this part definitely needs to be refactored
|
||||
// const userOrgs = await getOrganizations();
|
||||
// const userOrgsData = userOrgs.map((org: { _id: string }) => org._id);
|
||||
|
||||
// let orgToLogin;
|
||||
// if (userOrgsData.includes(localStorage.getItem('orgData.id'))) {
|
||||
// orgToLogin = localStorage.getItem('orgData.id');
|
||||
// } else {
|
||||
// orgToLogin = userOrgsData[0];
|
||||
// localStorage.setItem('orgData.id', orgToLogin);
|
||||
// }
|
||||
|
||||
// let orgUserProjects = await getOrganizationUserProjects({
|
||||
// orgId: orgToLogin
|
||||
// });
|
||||
|
||||
// orgUserProjects = orgUserProjects?.map((project: { _id: string }) => project._id);
|
||||
// let projectToLogin;
|
||||
// if (orgUserProjects.includes(localStorage.getItem('projectData.id'))) {
|
||||
// projectToLogin = localStorage.getItem('projectData.id');
|
||||
// } else {
|
||||
// try {
|
||||
// projectToLogin = orgUserProjects[0];
|
||||
// localStorage.setItem('projectData.id', projectToLogin);
|
||||
// } catch (error) {
|
||||
// console.log('ERROR: User likely has no projects. ', error);
|
||||
// }
|
||||
// }
|
||||
if (orgUserProjects.length > 0) {
|
||||
localStorage.setItem('projectData.id', orgUserProjects[0]._id);
|
||||
}
|
||||
|
||||
if (email) {
|
||||
telemetry.identify(email);
|
||||
@ -166,100 +140,4 @@ const attemptLogin = async (
|
||||
});
|
||||
};
|
||||
|
||||
export default attemptLogin;
|
||||
|
||||
// should be function: init first project
|
||||
|
||||
// if (isSignUp) {
|
||||
// const randomBytes = crypto.randomBytes(16).toString('hex');
|
||||
// const PRIVATE_KEY = String(localStorage.getItem('PRIVATE_KEY'));
|
||||
|
||||
// const myUser = await getUser();
|
||||
|
||||
// const { ciphertext, nonce } = encryptAssymmetric({
|
||||
// plaintext: randomBytes,
|
||||
// publicKey: myUser.publicKey,
|
||||
// privateKey: PRIVATE_KEY
|
||||
// }) as { ciphertext: string; nonce: string };
|
||||
|
||||
// await uploadKeys(projectToLogin, myUser._id, ciphertext, nonce);
|
||||
|
||||
// const secretsToBeAdded: SecretDataProps[] = [
|
||||
// {
|
||||
// pos: 0,
|
||||
// key: 'DATABASE_URL',
|
||||
// // eslint-disable-next-line no-template-curly-in-string
|
||||
// value: 'mongodb+srv://${DB_USERNAME}:${DB_PASSWORD}@mongodb.net',
|
||||
// valueOverride: undefined,
|
||||
// comment: 'Secret referencing example',
|
||||
// id: '',
|
||||
// tags: []
|
||||
// },
|
||||
// {
|
||||
// pos: 1,
|
||||
// key: 'DB_USERNAME',
|
||||
// value: 'OVERRIDE_THIS',
|
||||
// valueOverride: undefined,
|
||||
// comment:
|
||||
// 'Override secrets with personal value',
|
||||
// id: '',
|
||||
// tags: []
|
||||
// },
|
||||
// {
|
||||
// pos: 2,
|
||||
// key: 'DB_PASSWORD',
|
||||
// value: 'OVERRIDE_THIS',
|
||||
// valueOverride: undefined,
|
||||
// comment:
|
||||
// 'Another secret override',
|
||||
// id: '',
|
||||
// tags: []
|
||||
// },
|
||||
// {
|
||||
// pos: 3,
|
||||
// key: 'DB_USERNAME',
|
||||
// value: 'user1234',
|
||||
// valueOverride: 'user1234',
|
||||
// comment: '',
|
||||
// id: '',
|
||||
// tags: []
|
||||
// },
|
||||
// {
|
||||
// pos: 4,
|
||||
// key: 'DB_PASSWORD',
|
||||
// value: 'example_password',
|
||||
// valueOverride: 'example_password',
|
||||
// comment: '',
|
||||
// id: '',
|
||||
// tags: []
|
||||
// },
|
||||
// {
|
||||
// pos: 5,
|
||||
// key: 'TWILIO_AUTH_TOKEN',
|
||||
// value: 'example_twillio_token',
|
||||
// valueOverride: undefined,
|
||||
// comment: '',
|
||||
// id: '',
|
||||
// tags: []
|
||||
// },
|
||||
// {
|
||||
// pos: 6,
|
||||
// key: 'WEBSITE_URL',
|
||||
// value: 'http://localhost:3000',
|
||||
// valueOverride: undefined,
|
||||
// comment: '',
|
||||
// id: '',
|
||||
// tags: []
|
||||
// }
|
||||
// ];
|
||||
// const secrets = await encryptSecrets({
|
||||
// secretsToEncrypt: secretsToBeAdded,
|
||||
// workspaceId: String(localStorage.getItem('projectData.id')),
|
||||
// env: 'dev'
|
||||
// });
|
||||
// await addSecrets({
|
||||
// secrets: secrets ?? [],
|
||||
// env: 'dev',
|
||||
// workspaceId: String(localStorage.getItem('projectData.id'))
|
||||
// });
|
||||
// }
|
||||
export default attemptLogin;
|
@ -3,6 +3,8 @@ import jsrp from 'jsrp';
|
||||
|
||||
import login1 from '@app/pages/api/auth/Login1';
|
||||
import verifyMfaToken from '@app/pages/api/auth/verifyMfaToken';
|
||||
import getOrganizations from '@app/pages/api/organization/getOrgs';
|
||||
import getOrganizationUserProjects from '@app/pages/api/organization/GetOrgUserProjects';
|
||||
import KeyService from '@app/services/KeyService';
|
||||
|
||||
import { saveTokenToLocalStorage } from './saveTokenToLocalStorage';
|
||||
@ -51,7 +53,8 @@ const attemptLoginMfa = async ({
|
||||
mfaToken
|
||||
});
|
||||
|
||||
// set JWT token
|
||||
// unset temporary (MFA) JWT token and set JWT token
|
||||
SecurityClient.setMfaToken('');
|
||||
SecurityClient.setToken(token);
|
||||
|
||||
const privateKey = await KeyService.decryptPrivateKey({
|
||||
@ -77,6 +80,18 @@ const attemptLoginMfa = async ({
|
||||
privateKey
|
||||
});
|
||||
|
||||
// TODO: in the future - move this logic elsewhere
|
||||
// because this function is about logging the user in
|
||||
// and not initializing the login details
|
||||
const userOrgs = await getOrganizations();
|
||||
const orgId = userOrgs[0]._id;
|
||||
localStorage.setItem('orgData.id', orgId);
|
||||
|
||||
const orgUserProjects = await getOrganizationUserProjects({
|
||||
orgId
|
||||
});
|
||||
localStorage.setItem('projectData.id', orgUserProjects[0]._id);
|
||||
|
||||
resolve(true);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
|
@ -1,6 +1,9 @@
|
||||
import axios from 'axios';
|
||||
|
||||
import { getAuthToken } from '@app/reactQuery';
|
||||
import {
|
||||
getAuthToken,
|
||||
getMfaTempToken,
|
||||
getSignupTempToken} from '@app/reactQuery';
|
||||
|
||||
export const apiRequest = axios.create({
|
||||
baseURL: '/',
|
||||
@ -10,11 +13,17 @@ export const apiRequest = axios.create({
|
||||
});
|
||||
|
||||
apiRequest.interceptors.request.use((config) => {
|
||||
const signupTempToken = getSignupTempToken();
|
||||
const mfaTempToken = getMfaTempToken();
|
||||
const token = getAuthToken();
|
||||
console.log('interceptors');
|
||||
console.log('token', token);
|
||||
console.log('config.headers', config.headers);
|
||||
if (token && config.headers) {
|
||||
|
||||
if (signupTempToken && config.headers) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
config.headers.Authorization = `Bearer ${signupTempToken}`;
|
||||
} else if (mfaTempToken && config.headers) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
config.headers.Authorization = `Bearer ${mfaTempToken}`;
|
||||
} else if (token && config.headers) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
|
@ -1 +1,4 @@
|
||||
export { useGetAuthToken } from './queries';
|
||||
export {
|
||||
useGetAuthToken,
|
||||
useSendMfaToken,
|
||||
useVerifyMfaToken} from './queries'
|
||||
|
@ -1,14 +1,39 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { apiRequest } from '@app/config/request';
|
||||
import { setAuthToken } from '@app/reactQuery';
|
||||
|
||||
import { GetAuthTokenAPI } from './types';
|
||||
import {
|
||||
GetAuthTokenAPI,
|
||||
SendMfaTokenDTO,
|
||||
VerifyMfaTokenDTO,
|
||||
VerifyMfaTokenRes} from './types';
|
||||
|
||||
const authKeys = {
|
||||
getAuthToken: ['token'] as const
|
||||
};
|
||||
|
||||
export const useSendMfaToken = () => {
|
||||
return useMutation<{}, {}, SendMfaTokenDTO>({
|
||||
mutationFn: async ({ email }) => {
|
||||
const { data } = await apiRequest.post('/api/v2/auth/mfa/send', { email });
|
||||
return data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export const useVerifyMfaToken = () => {
|
||||
return useMutation<VerifyMfaTokenRes, {}, VerifyMfaTokenDTO>({
|
||||
mutationFn: async ({ email, mfaCode }) => {
|
||||
const { data } = await apiRequest.post('/api/v2/auth/mfa/verify', {
|
||||
email,
|
||||
mfaToken: mfaCode
|
||||
});
|
||||
return data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Refresh token is set as cookie when logged in
|
||||
// Using that we fetch the auth bearer token needed for auth calls
|
||||
const fetchAuthToken = async () => {
|
||||
|
@ -1,3 +1,24 @@
|
||||
export type GetAuthTokenAPI = {
|
||||
token: string;
|
||||
};
|
||||
|
||||
export type SendMfaTokenDTO = {
|
||||
email: string;
|
||||
}
|
||||
|
||||
export type VerifyMfaTokenDTO = {
|
||||
email: string;
|
||||
mfaCode: string;
|
||||
}
|
||||
|
||||
export type VerifyMfaTokenRes = {
|
||||
encryptionVersion: number;
|
||||
protectedKey?: string;
|
||||
protectedKeyIV?: string;
|
||||
protectedKeyTag?: string;
|
||||
token: string;
|
||||
publicKey: string;
|
||||
encryptedPrivateKey: string;
|
||||
iv: string;
|
||||
tag: string;
|
||||
}
|
@ -93,6 +93,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
||||
// Placing the localstorage as much as possible
|
||||
// Wait till tony integrates the azure and its launched
|
||||
useEffect(() => {
|
||||
|
||||
// Put a user in a workspace if they're not in one yet
|
||||
const putUserInWorkSpace = async () => {
|
||||
if (tempLocalStorage('orgData.id') === '') {
|
||||
|
@ -75,8 +75,18 @@ export const Navbar = () => {
|
||||
|
||||
const closeApp = async () => {
|
||||
try {
|
||||
console.log('Logging out...');
|
||||
console.log('Logging out...')
|
||||
await logout.mutateAsync();
|
||||
localStorage.removeItem('protectedKey');
|
||||
localStorage.removeItem('protectedKeyIV');
|
||||
localStorage.removeItem('protectedKeyTag');
|
||||
localStorage.removeItem('publicKey');
|
||||
localStorage.removeItem('encryptedPrivateKey');
|
||||
localStorage.removeItem('iv');
|
||||
localStorage.removeItem('tag');
|
||||
localStorage.removeItem('PRIVATE_KEY');
|
||||
localStorage.removeItem('orgData.id');
|
||||
localStorage.removeItem('projectData.id');
|
||||
router.push('/login');
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
|
@ -1,4 +1,5 @@
|
||||
import SecurityClient from '@app/components/utilities/SecurityClient';
|
||||
|
||||
import { apiRequest } from "@app/config/request";
|
||||
|
||||
interface Props {
|
||||
email: string;
|
||||
@ -35,7 +36,7 @@ interface Props {
|
||||
* @param {string} obj.verifier
|
||||
* @returns
|
||||
*/
|
||||
const completeAccountInformationSignup = ({
|
||||
const completeAccountInformationSignup = async ({
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
@ -49,32 +50,24 @@ const completeAccountInformationSignup = ({
|
||||
salt,
|
||||
verifier,
|
||||
organizationName
|
||||
}: Props) => SecurityClient.fetchCall('/api/v2/signup/complete-account/signup', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
protectedKey,
|
||||
protectedKeyIV,
|
||||
protectedKeyTag,
|
||||
publicKey,
|
||||
encryptedPrivateKey,
|
||||
encryptedPrivateKeyIV,
|
||||
encryptedPrivateKeyTag,
|
||||
salt,
|
||||
verifier,
|
||||
organizationName
|
||||
})
|
||||
}).then(async (res) => {
|
||||
if (res && res?.status === 200) {
|
||||
return res.json();
|
||||
}
|
||||
console.log('Failed to verify MFA code');
|
||||
throw new Error('Something went wrong during MFA code verification');
|
||||
}: Props) => {
|
||||
const { data } = await apiRequest.post('/api/v2/signup/complete-account/signup', {
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
protectedKey,
|
||||
protectedKeyIV,
|
||||
protectedKeyTag,
|
||||
publicKey,
|
||||
encryptedPrivateKey,
|
||||
encryptedPrivateKeyIV,
|
||||
encryptedPrivateKeyTag,
|
||||
salt,
|
||||
verifier,
|
||||
organizationName
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
export default completeAccountInformationSignup;
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { apiRequest } from "@app/config/request";
|
||||
|
||||
interface Props {
|
||||
email: string;
|
||||
firstName: string;
|
||||
@ -11,9 +13,12 @@ interface Props {
|
||||
encryptedPrivateKeyTag: string;
|
||||
salt: string;
|
||||
verifier: string;
|
||||
token: string;
|
||||
}
|
||||
|
||||
// missing token?
|
||||
// TODO: add to SecurityClient
|
||||
|
||||
|
||||
/**
|
||||
* This function is called in the end of the signup process.
|
||||
* It sends all the necessary nformation to the server.
|
||||
@ -30,7 +35,7 @@ interface Props {
|
||||
* @param {string} obj.token - token that confirms a user's identity
|
||||
* @returns
|
||||
*/
|
||||
const completeAccountInformationSignupInvite = ({
|
||||
const completeAccountInformationSignupInvite = async ({
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
@ -42,28 +47,24 @@ const completeAccountInformationSignupInvite = ({
|
||||
encryptedPrivateKeyIV,
|
||||
encryptedPrivateKeyTag,
|
||||
salt,
|
||||
verifier,
|
||||
token
|
||||
}: Props) => fetch('/api/v2/signup/complete-account/invite', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${token}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
protectedKey,
|
||||
protectedKeyIV,
|
||||
protectedKeyTag,
|
||||
publicKey,
|
||||
encryptedPrivateKey,
|
||||
encryptedPrivateKeyIV,
|
||||
encryptedPrivateKeyTag,
|
||||
salt,
|
||||
verifier
|
||||
})
|
||||
verifier
|
||||
}: Props) => {
|
||||
const { data } = await apiRequest.post('/api/v2/signup/complete-account/invite', {
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
protectedKey,
|
||||
protectedKeyIV,
|
||||
protectedKeyTag,
|
||||
publicKey,
|
||||
encryptedPrivateKey,
|
||||
encryptedPrivateKeyIV,
|
||||
encryptedPrivateKeyTag,
|
||||
salt,
|
||||
verifier
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
export default completeAccountInformationSignupInvite;
|
||||
|
@ -4,14 +4,16 @@ import SecurityClient from '@app/components/utilities/SecurityClient';
|
||||
* This route logs the user out. Note: the user should authorized to do this.
|
||||
* We first try to log out - if the authorization fails (response.status = 401), we refetch the new token, and then retry
|
||||
*/
|
||||
const logout = async () =>
|
||||
SecurityClient.fetchCall('/api/v1/auth/logout', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'include'
|
||||
}).then((res) => {
|
||||
const logout = async () => {
|
||||
try {
|
||||
const res = await SecurityClient.fetchCall('/api/v1/auth/logout', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
if (res?.status === 200) {
|
||||
SecurityClient.setToken('');
|
||||
// Delete the cookie by not setting a value; Alternatively clear the local storage
|
||||
@ -23,12 +25,17 @@ const logout = async () =>
|
||||
localStorage.removeItem('iv');
|
||||
localStorage.removeItem('tag');
|
||||
localStorage.removeItem('PRIVATE_KEY');
|
||||
localStorage.removeItem('orgData.id');
|
||||
localStorage.removeItem('projectData.id');
|
||||
|
||||
console.log('User logged out', res);
|
||||
return res;
|
||||
}
|
||||
console.log('Failed to log out');
|
||||
return undefined;
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.log('Error logging out', error);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export default logout;
|
||||
|
@ -1,29 +0,0 @@
|
||||
import SecurityClient from "@app/components/utilities/SecurityClient";
|
||||
|
||||
/**
|
||||
* Send new MFA token to user with email [email]
|
||||
* @param {object} obj
|
||||
* @param {string} obj.email - email of user
|
||||
* @returns
|
||||
*/
|
||||
const resendMfaToken = async ({
|
||||
email,
|
||||
}: {
|
||||
email: string;
|
||||
}) => SecurityClient.fetchCall('/api/v2/auth/mfa/send', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email
|
||||
})
|
||||
}).then(async (res) => {
|
||||
if (res && res?.status === 200) {
|
||||
return res.json();
|
||||
}
|
||||
console.log('Failed to send new MFA code');
|
||||
throw new Error('Something went wrong while sending new MFA code');
|
||||
});
|
||||
|
||||
export default resendMfaToken;
|
@ -1,4 +1,4 @@
|
||||
import SecurityClient from "@app/components/utilities/SecurityClient";
|
||||
import { apiRequest } from "@app/config/request";
|
||||
|
||||
/**
|
||||
* Verify MFA token [mfaToken] for user with email [email]
|
||||
@ -13,23 +13,13 @@ const verifyMfaToken = async ({
|
||||
}: {
|
||||
email: string;
|
||||
mfaToken: string;
|
||||
}) => SecurityClient.fetchCall('/api/v2/auth/mfa/verify', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
mfaToken
|
||||
})
|
||||
}).then(async (res) => {
|
||||
if (res && res?.status === 200) {
|
||||
return res.json();
|
||||
}
|
||||
console.log('Failed to verify MFA code');
|
||||
throw new Error('Something went wrong during MFA code verification');
|
||||
});
|
||||
|
||||
|
||||
}) => {
|
||||
const { data } = await apiRequest.post('/api/v2/auth/mfa/verify', {
|
||||
email,
|
||||
mfaToken
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
export default verifyMfaToken;
|
||||
|
@ -17,7 +17,6 @@ export default function Login() {
|
||||
const router = useRouter();
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [isAlreadyLoggedIn, setIsAlreadyLoggedIn] = useState(false);
|
||||
const [step, setStep] = useState(1);
|
||||
const { t } = useTranslation();
|
||||
const lang = router.locale ?? 'en';
|
||||
@ -41,7 +40,6 @@ export default function Login() {
|
||||
}
|
||||
};
|
||||
if (isLoggedIn()) {
|
||||
setIsAlreadyLoggedIn(true);
|
||||
redirectToDashboard();
|
||||
}
|
||||
}, []);
|
||||
@ -72,10 +70,6 @@ export default function Login() {
|
||||
}
|
||||
}
|
||||
|
||||
if (isAlreadyLoggedIn) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-bunker-800 h-screen flex flex-col justify-start px-6">
|
||||
<Head>
|
||||
@ -106,4 +100,4 @@ export default function Login() {
|
||||
);
|
||||
}
|
||||
|
||||
export const getStaticProps = getTranslatedStaticProps(['auth', 'login']);
|
||||
export const getStaticProps = getTranslatedStaticProps(['auth', 'login', 'signup']);
|
||||
|
@ -59,7 +59,8 @@ export default function SignUp() {
|
||||
// Checking if the code matches the email.
|
||||
const response = await checkEmailVerificationCode({ email, code });
|
||||
if (response.status === 200) {
|
||||
SecurityClient.setToken((await response.json()).token);
|
||||
const {token} = await response.json();
|
||||
SecurityClient.setSignupToken(token);
|
||||
setStep(3);
|
||||
} else {
|
||||
setCodeError(true);
|
||||
|
@ -21,6 +21,10 @@ import passwordCheck from '@app/components/utilities/checks/PasswordCheck';
|
||||
import Aes256Gcm from '@app/components/utilities/cryptography/aes-256-gcm';
|
||||
import { deriveArgonKey } from '@app/components/utilities/cryptography/crypto';
|
||||
import issueBackupKey from '@app/components/utilities/cryptography/issueBackupKey';
|
||||
import { saveTokenToLocalStorage } from '@app/components/utilities/saveTokenToLocalStorage';
|
||||
import SecurityClient from '@app/components/utilities/SecurityClient';
|
||||
import getOrganizations from '@app/pages/api/organization/getOrgs';
|
||||
import getOrganizationUserProjects from '@app/pages/api/organization/GetOrgUserProjects';
|
||||
|
||||
import completeAccountInformationSignupInvite from './api/auth/CompleteAccountInformationSignupInvite';
|
||||
import verifySignupInvite from './api/auth/VerifySignupInvite';
|
||||
@ -29,7 +33,6 @@ import verifySignupInvite from './api/auth/VerifySignupInvite';
|
||||
const client = new jsrp.client();
|
||||
|
||||
export default function SignupInvite() {
|
||||
console.log('SignupInvite');
|
||||
const [password, setPassword] = useState('');
|
||||
const [firstName, setFirstName] = useState('');
|
||||
const [lastName, setLastName] = useState('');
|
||||
@ -82,13 +85,6 @@ export default function SignupInvite() {
|
||||
const privateKey = encodeBase64(secretKeyUint8Array);
|
||||
const publicKey = encodeBase64(publicKeyUint8Array);
|
||||
|
||||
// const { ciphertext, iv, tag } = Aes256Gcm.encrypt({
|
||||
// text: PRIVATE_KEY,
|
||||
// secret: password
|
||||
// .slice(0, 32)
|
||||
// .padStart(32 + (password.slice(0, 32).length - new Blob([password]).size), '0')
|
||||
// });
|
||||
|
||||
localStorage.setItem('PRIVATE_KEY', privateKey);
|
||||
|
||||
client.init(
|
||||
@ -134,8 +130,9 @@ export default function SignupInvite() {
|
||||
secret: Buffer.from(derivedKey.hash)
|
||||
});
|
||||
|
||||
console.log('SignupInvite A');
|
||||
let response = await completeAccountInformationSignupInvite({
|
||||
const {
|
||||
token: jwtToken
|
||||
} = await completeAccountInformationSignupInvite({
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
@ -147,24 +144,30 @@ export default function SignupInvite() {
|
||||
encryptedPrivateKeyIV,
|
||||
encryptedPrivateKeyTag,
|
||||
salt: result.salt,
|
||||
verifier: result.verifier,
|
||||
token: verificationToken
|
||||
verifier: result.verifier
|
||||
});
|
||||
console.log('SignupInvite B');
|
||||
|
||||
// unset temporary signup JWT token and set JWT token
|
||||
SecurityClient.setSignupToken('');
|
||||
SecurityClient.setToken(jwtToken);
|
||||
|
||||
// if everything works, go the main dashboard page.
|
||||
if (!errorCheck && response.status === 200) {
|
||||
response = await response.json();
|
||||
saveTokenToLocalStorage({
|
||||
protectedKey,
|
||||
protectedKeyIV,
|
||||
protectedKeyTag,
|
||||
publicKey,
|
||||
encryptedPrivateKey,
|
||||
iv: encryptedPrivateKeyIV,
|
||||
tag: encryptedPrivateKeyTag,
|
||||
privateKey
|
||||
});
|
||||
|
||||
console.log('SignupInvite C');
|
||||
localStorage.setItem('publicKey', publicKey);
|
||||
localStorage.setItem('encryptedPrivateKey', encryptedPrivateKey);
|
||||
localStorage.setItem('iv', encryptedPrivateKeyIV);
|
||||
localStorage.setItem('tag', encryptedPrivateKeyTag);
|
||||
console.log('SignupInvite D');
|
||||
const userOrgs = await getOrganizations();
|
||||
|
||||
setStep(3);
|
||||
}
|
||||
const orgId = userOrgs[0]._id;
|
||||
localStorage.setItem('orgData.id', orgId);
|
||||
|
||||
setStep(3);
|
||||
} catch (error) {
|
||||
setIsLoading(false);
|
||||
console.error(error);
|
||||
@ -197,7 +200,7 @@ export default function SignupInvite() {
|
||||
// user will have temp token if doesn't have an account
|
||||
// then continue with account setup workflow
|
||||
if (res?.token) {
|
||||
setVerificationToken(res.token);
|
||||
SecurityClient.setSignupToken(res.token);
|
||||
setStep(2);
|
||||
} else {
|
||||
// user will be redirected to dashboard
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { QueryClient } from '@tanstack/react-query';
|
||||
|
||||
// this is saved in react-query cache
|
||||
export const SIGNUP_TEMP_TOKEN_CACHE_KEY = ['infisical__signup-temp-token'];
|
||||
export const MFA_TEMP_TOKEN_CACHE_KEY = ['infisical__mfa-temp-token'];
|
||||
export const AUTH_TOKEN_CACHE_KEY = ['infisical__auth-token'];
|
||||
|
||||
@ -14,12 +15,16 @@ export const queryClient = new QueryClient({
|
||||
});
|
||||
|
||||
// set token in memory cache
|
||||
export const setSignupTempToken = (token: string) =>
|
||||
queryClient.setQueryData(SIGNUP_TEMP_TOKEN_CACHE_KEY, token);
|
||||
|
||||
export const setMfaTempToken = (token: string) =>
|
||||
queryClient.setQueryData(MFA_TEMP_TOKEN_CACHE_KEY, token);
|
||||
|
||||
export const setAuthToken = (token: string) =>
|
||||
queryClient.setQueryData(AUTH_TOKEN_CACHE_KEY, token);
|
||||
|
||||
export const getSignupTempToken = () => queryClient.getQueryData(SIGNUP_TEMP_TOKEN_CACHE_KEY) as string;
|
||||
export const getMfaTempToken = () => queryClient.getQueryData(MFA_TEMP_TOKEN_CACHE_KEY) as string;
|
||||
export const getAuthToken = () => queryClient.getQueryData(AUTH_TOKEN_CACHE_KEY) as string;
|
||||
|
||||
|
Reference in New Issue
Block a user