diff --git a/backend/src/controllers/membershipOrgController.ts b/backend/src/controllers/membershipOrgController.ts
index bc2804996..a2159bcd0 100644
--- a/backend/src/controllers/membershipOrgController.ts
+++ b/backend/src/controllers/membershipOrgController.ts
@@ -217,7 +217,7 @@ export const verifyUserToOrganization = async (req: Request, res: Response) => {
try {
const { email, code } = req.body;
- user = await User.findOne({ email });
+ user = await User.findOne({ email }).select('+publicKey');
if (user && user?.publicKey) {
// case: user has already completed account
return res.status(403).send({
@@ -257,7 +257,7 @@ export const verifyUserToOrganization = async (req: Request, res: Response) => {
Sentry.setUser(null);
Sentry.captureException(err);
return res.status(400).send({
- error: 'Failed email magic link confirmation'
+ error: 'Failed email magic link verification for organization invitation'
});
}
diff --git a/backend/src/controllers/passwordController.ts b/backend/src/controllers/passwordController.ts
index 86b5355db..0109dc6a5 100644
--- a/backend/src/controllers/passwordController.ts
+++ b/backend/src/controllers/passwordController.ts
@@ -1,11 +1,121 @@
import { Request, Response } from 'express';
import * as Sentry from '@sentry/node';
+import crypto from 'crypto';
const jsrp = require('jsrp');
import * as bigintConversion from 'bigint-conversion';
-import { User, BackupPrivateKey } from '../models';
+import { User, Token, BackupPrivateKey } from '../models';
+import { checkEmailVerification } from '../helpers/signup';
+import { createToken } from '../helpers/auth';
+import { sendMail } from '../helpers/nodemailer';
+import { JWT_SIGNUP_LIFETIME, JWT_SIGNUP_SECRET, SITE_URL } from '../config';
const clientPublicKeys: any = {};
+/**
+ * Password reset step 1: Send email verification link to email [email]
+ * for account recovery.
+ * @param req
+ * @param res
+ * @returns
+ */
+export const emailPasswordReset = async (req: Request, res: Response) => {
+ let email: string;
+ try {
+ email = req.body.email;
+
+ const user = await User.findOne({ email }).select('+publicKey');
+ if (!user || !user?.publicKey) {
+ // case: user has already completed account
+
+ return res.status(403).send({
+ error: 'Failed to send email verification for password reset'
+ });
+ }
+
+ const token = crypto.randomBytes(16).toString('hex');
+
+ await Token.findOneAndUpdate(
+ { email },
+ {
+ email,
+ token,
+ createdAt: new Date()
+ },
+ { upsert: true, new: true }
+ );
+
+ await sendMail({
+ template: 'passwordReset.handlebars',
+ subjectLine: 'Infisical password reset',
+ recipients: [email],
+ substitutions: {
+ email,
+ token,
+ callback_url: SITE_URL + '/password-reset'
+ }
+ });
+
+ } catch (err) {
+ Sentry.setUser(null);
+ Sentry.captureException(err);
+ return res.status(400).send({
+ message: 'Failed to send email for account recovery'
+ });
+ }
+
+ return res.status(200).send({
+ message: `Sent an email for account recovery to ${email}`
+ });
+}
+
+/**
+ * Password reset step 2: Verify email verification link sent to email [email]
+ * @param req
+ * @param res
+ * @returns
+ */
+export const emailPasswordResetVerify = async (req: Request, res: Response) => {
+ let user, token;
+ try {
+ const { email, code } = req.body;
+
+ user = await User.findOne({ email }).select('+publicKey');
+ if (!user || !user?.publicKey) {
+ // case: user doesn't exist with email [email] or
+ // hasn't even completed their account
+ return res.status(403).send({
+ error: 'Failed email verification for password reset'
+ });
+ }
+
+ await checkEmailVerification({
+ email,
+ code
+ });
+
+ // generate temporary password-reset token
+ token = createToken({
+ payload: {
+ userId: user._id.toString()
+ },
+ expiresIn: JWT_SIGNUP_LIFETIME,
+ secret: JWT_SIGNUP_SECRET
+ });
+ } catch (err) {
+ Sentry.setUser(null);
+ Sentry.captureException(err);
+ return res.status(400).send({
+ message: 'Failed email verification for password reset'
+ });
+ }
+
+ return res.status(200).send({
+ message: 'Successfully verified email',
+ user,
+ token
+ });
+}
+
/**
* Return [salt] and [serverPublicKey] as part of step 1 of SRP protocol
* @param req
@@ -43,7 +153,7 @@ export const srp1 = async (req: Request, res: Response) => {
}
);
} catch (err) {
- Sentry.setUser(null);
+ Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
return res.status(400).send({
error: 'Failed to start change password process'
@@ -110,7 +220,7 @@ export const changePassword = async (req: Request, res: Response) => {
}
);
} catch (err) {
- Sentry.setUser(null);
+ Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
return res.status(400).send({
error: 'Failed to change password. Try again?'
@@ -180,10 +290,73 @@ export const createBackupPrivateKey = async (req: Request, res: Response) => {
}
);
} catch (err) {
- Sentry.setUser(null);
+ Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
return res.status(400).send({
message: 'Failed to update backup private key'
});
}
};
+
+/**
+ * Return backup private key for user
+ * @param req
+ * @param res
+ * @returns
+ */
+export const getBackupPrivateKey = async (req: Request, res: Response) => {
+ let backupPrivateKey;
+ try {
+ backupPrivateKey = await BackupPrivateKey.findOne({
+ user: req.user._id
+ });
+
+ if (!backupPrivateKey) throw new Error('Failed to find backup private key');
+ } catch (err) {
+ Sentry.setUser({ email: req.user.email});
+ Sentry.captureException(err);
+ return res.status(400).send({
+ message: 'Failed to get backup private key'
+ });
+ }
+
+ return res.status(200).send({
+ backupPrivateKey
+ });
+}
+
+export const resetPassword = async (req: Request, res: Response) => {
+ try {
+ const {
+ encryptedPrivateKey,
+ iv,
+ tag,
+ salt,
+ verifier,
+ } = req.body;
+
+ await User.findByIdAndUpdate(
+ req.user._id.toString(),
+ {
+ encryptedPrivateKey,
+ iv,
+ tag,
+ salt,
+ verifier
+ },
+ {
+ new: true
+ }
+ );
+ } catch (err) {
+ Sentry.setUser({ email: req.user.email});
+ Sentry.captureException(err);
+ return res.status(400).send({
+ message: 'Failed to get backup private key'
+ });
+ }
+
+ return res.status(200).send({
+ message: 'Successfully reset password'
+ });
+}
\ No newline at end of file
diff --git a/backend/src/routes/password.ts b/backend/src/routes/password.ts
index 5d39eac28..955e532a0 100644
--- a/backend/src/routes/password.ts
+++ b/backend/src/routes/password.ts
@@ -1,7 +1,7 @@
import express from 'express';
const router = express.Router();
import { body } from 'express-validator';
-import { requireAuth, validateRequest } from '../middleware';
+import { requireAuth, requireSignupAuth, validateRequest } from '../middleware';
import { passwordController } from '../controllers';
import { passwordLimiter } from '../helpers/rateLimiter';
@@ -27,6 +27,33 @@ router.post(
passwordController.changePassword
);
+// NEW
+router.post(
+ '/email/password-reset',
+ passwordLimiter,
+ body('email').exists().trim().notEmpty(),
+ validateRequest,
+ passwordController.emailPasswordReset
+);
+
+// NEW
+router.post(
+ '/email/password-reset-verify',
+ passwordLimiter,
+ body('email').exists().trim().notEmpty().isEmail(),
+ body('code').exists().trim().notEmpty(),
+ validateRequest,
+ passwordController.emailPasswordResetVerify
+);
+
+// NEW
+router.get(
+ '/backup-private-key',
+ passwordLimiter,
+ requireSignupAuth,
+ passwordController.getBackupPrivateKey
+);
+
router.post(
'/backup-private-key',
passwordLimiter,
@@ -41,4 +68,17 @@ router.post(
passwordController.createBackupPrivateKey
);
-export default router;
+// NEW
+router.post(
+ '/password-reset',
+ requireSignupAuth,
+ body('encryptedPrivateKey').exists().trim().notEmpty(), // private key encrypted under new pwd
+ body('iv').exists().trim().notEmpty(), // new iv for private key
+ body('tag').exists().trim().notEmpty(), // new tag for private key
+ body('salt').exists().trim().notEmpty(), // part of new pwd
+ body('verifier').exists().trim().notEmpty(), // part of new pwd
+ validateRequest,
+ passwordController.resetPassword
+);
+
+export default router;
\ No newline at end of file
diff --git a/backend/src/templates/organizationInvitation.handlebars b/backend/src/templates/organizationInvitation.handlebars
index 663409188..49cc96f38 100644
--- a/backend/src/templates/organizationInvitation.handlebars
+++ b/backend/src/templates/organizationInvitation.handlebars
@@ -4,7 +4,7 @@
- Email Verification
+ Organization Invitation
Infisical
diff --git a/backend/src/templates/passwordReset.handlebars b/backend/src/templates/passwordReset.handlebars
new file mode 100644
index 000000000..1e629f664
--- /dev/null
+++ b/backend/src/templates/passwordReset.handlebars
@@ -0,0 +1,15 @@
+
+
+
+
+
+ Account Recovery
+
+
+ Infisical
+ Reset your password
+ Someone requested a password reset.
+ Reset password
+ If you didn't initiate this request, please contact us immediately at team@infisical.com
+
+
\ No newline at end of file
diff --git a/backend/src/templates/workspaceInvitation.handlebars b/backend/src/templates/workspaceInvitation.handlebars
index 22f63efc9..252452ce5 100644
--- a/backend/src/templates/workspaceInvitation.handlebars
+++ b/backend/src/templates/workspaceInvitation.handlebars
@@ -3,7 +3,7 @@
- Email Verification
+ Project Invitation
Infisical
diff --git a/docs/integrations/cloud/vercel.mdx b/docs/integrations/cloud/vercel.mdx
new file mode 100644
index 000000000..eb09203b5
--- /dev/null
+++ b/docs/integrations/cloud/vercel.mdx
@@ -0,0 +1,5 @@
+---
+title: "Vercel"
+---
+
+Coming soon.
diff --git a/docs/integrations/overview.mdx b/docs/integrations/overview.mdx
index 17c7a7f72..9323f8917 100644
--- a/docs/integrations/overview.mdx
+++ b/docs/integrations/overview.mdx
@@ -12,7 +12,7 @@ Missing an integration? Throw in a [request](https://github.com/Infisical/infisi
| [Docker-Compose](/integrations/platforms/docker-compose) | Platform | Available |
| Kubernetes | Platform | Coming soon |
| [Heroku](/integrations/cloud/heroku) | Cloud | Available |
-| Vercel | Cloud | Coming soon |
+| [Vercel](/integrations/cloud/vercel) | Cloud | Coming soon |
| AWS | Cloud | Coming soon |
| GCP | Cloud | Coming soon |
| Azure | Cloud | Coming soon |
@@ -31,8 +31,8 @@ Missing an integration? Throw in a [request](https://github.com/Infisical/infisi
| [Gatsby](/integrations/frameworks/gatsby) | Framework | Available |
| [Remix](/integrations/frameworks/remix) | Framework | Available |
| [Vite](/integrations/frameworks/vite) | Framework | Available |
-| [Fiber](/integrations/frameworks/fiber) | Framework | Coming soon |
+| [Fiber](/integrations/frameworks/fiber) | Framework | Available |
| [Django](/integrations/frameworks/django) | Framework | Available |
| [Flask](/integrations/frameworks/flask) | Framework | Available |
-| [Laravel](/integrations/frameworks/laravel) | Framework | Coming soon |
+| [Laravel](/integrations/frameworks/laravel) | Framework | Available |
| [Ruby on Rails](/integrations/frameworks/rails) | Framework | Available |
diff --git a/docs/mint.json b/docs/mint.json
index 4fa0436d8..547291fa5 100644
--- a/docs/mint.json
+++ b/docs/mint.json
@@ -130,7 +130,8 @@
{
"group": "Cloud",
"pages": [
- "integrations/cloud/heroku"
+ "integrations/cloud/heroku",
+ "integrations/cloud/vercel"
]
},
{
diff --git a/frontend/components/basic/dialog/AddServiceTokenDialog.js b/frontend/components/basic/dialog/AddServiceTokenDialog.js
index 7ff1789b8..ab116cf4d 100644
--- a/frontend/components/basic/dialog/AddServiceTokenDialog.js
+++ b/frontend/components/basic/dialog/AddServiceTokenDialog.js
@@ -1,39 +1,39 @@
-import { Fragment, useState } from "react";
-import { useRouter } from "next/router";
-import { faCheck, faCopy } from "@fortawesome/free-solid-svg-icons";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { Dialog, Transition } from "@headlessui/react";
-import nacl from "tweetnacl";
+import { Fragment, useState } from 'react';
+import { faCheck, faCopy } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Dialog, Transition } from '@headlessui/react';
+import nacl from 'tweetnacl';
-import addServiceToken from "~/pages/api/serviceToken/addServiceToken";
-import getLatestFileKey from "~/pages/api/workspace/getLatestFileKey";
+import addServiceToken from '~/pages/api/serviceToken/addServiceToken';
+import getLatestFileKey from '~/pages/api/workspace/getLatestFileKey';
-import { envMapping } from "../../../public/data/frequentConstants";
+import { envMapping } from '../../../public/data/frequentConstants';
import {
decryptAssymmetric,
- encryptAssymmetric,
-} from "../../utilities/cryptography/crypto";
-import Button from "../buttons/Button";
-import InputField from "../InputField";
-import ListBox from "../Listbox";
+ encryptAssymmetric
+} from '../../utilities/cryptography/crypto';
+import Button from '../buttons/Button';
+import InputField from '../InputField';
+import ListBox from '../Listbox';
const expiryMapping = {
- "1 day": 86400,
- "7 days": 604800,
- "1 month": 2592000,
+ '1 day': 86400,
+ '7 days': 604800,
+ '1 month': 2592000,
+ '6 months': 15552000,
+ '12 months': 31104000
};
const AddServiceTokenDialog = ({
isOpen,
closeModal,
workspaceId,
- workspaceName,
+ workspaceName
}) => {
- const router = useRouter();
- const [serviceToken, setServiceToken] = useState("");
- const [serviceTokenName, setServiceTokenName] = useState("");
- const [serviceTokenEnv, setServiceTokenEnv] = useState("Development");
- const [serviceTokenExpiresIn, setServiceTokenExpiresIn] = useState("1 day");
+ const [serviceToken, setServiceToken] = useState('');
+ const [serviceTokenName, setServiceTokenName] = useState('');
+ const [serviceTokenEnv, setServiceTokenEnv] = useState('Development');
+ const [serviceTokenExpiresIn, setServiceTokenExpiresIn] = useState('1 day');
const [serviceTokenCopied, setServiceTokenCopied] = useState(false);
const generateServiceToken = async () => {
@@ -43,7 +43,7 @@ const AddServiceTokenDialog = ({
ciphertext: latestFileKey.latestKey.encryptedKey,
nonce: latestFileKey.latestKey.nonce,
publicKey: latestFileKey.latestKey.sender.publicKey,
- privateKey: localStorage.getItem("PRIVATE_KEY"),
+ privateKey: localStorage.getItem('PRIVATE_KEY')
});
// generate new public/private key pair
@@ -55,7 +55,7 @@ const AddServiceTokenDialog = ({
const { ciphertext: encryptedKey, nonce } = encryptAssymmetric({
plaintext: key,
publicKey,
- privateKey,
+ privateKey
});
let newServiceToken = await addServiceToken({
@@ -65,16 +65,16 @@ const AddServiceTokenDialog = ({
expiresIn: expiryMapping[serviceTokenExpiresIn],
publicKey,
encryptedKey,
- nonce,
+ nonce
});
- const serviceToken = newServiceToken + "," + privateKey;
+ const serviceToken = newServiceToken + ',' + privateKey;
setServiceToken(serviceToken);
};
function copyToClipboard() {
// Get the text field
- var copyText = document.getElementById("serviceToken");
+ var copyText = document.getElementById('serviceToken');
// Select the text field
copyText.select();
@@ -91,8 +91,8 @@ const AddServiceTokenDialog = ({
const closeAddServiceTokenModal = () => {
closeModal();
- setServiceTokenName("");
- setServiceToken("");
+ setServiceTokenName('');
+ setServiceToken('');
};
return (
@@ -122,7 +122,7 @@ const AddServiceTokenDialog = ({
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
- {serviceToken == "" ? (
+ {serviceToken == '' ? (
@@ -168,8 +168,14 @@ const AddServiceTokenDialog = ({
@@ -181,7 +187,7 @@ const AddServiceTokenDialog = ({
text="Add Service Token"
textDisabled="Add Service Token"
size="md"
- active={serviceTokenName == "" ? false : true}
+ active={serviceTokenName == '' ? false : true}
/>
diff --git a/frontend/components/context/Notifications/Notification.tsx b/frontend/components/context/Notifications/Notification.tsx
index e473ddb52..ad556a6f5 100644
--- a/frontend/components/context/Notifications/Notification.tsx
+++ b/frontend/components/context/Notifications/Notification.tsx
@@ -1,9 +1,8 @@
-import { useEffect, useRef } from "react";
-import { faXmarkCircle } from "@fortawesome/free-solid-svg-icons";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import classnames from "classnames";
+import { useEffect, useRef } from 'react';
+import { faX } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Notification as NotificationType } from "./NotificationProvider";
+import { Notification as NotificationType } from './NotificationProvider';
interface NotificationProps {
notification: Required;
@@ -12,7 +11,7 @@ interface NotificationProps {
const Notification = ({
notification,
- clearNotification,
+ clearNotification
}: NotificationProps) => {
const timeout = useRef();
@@ -37,22 +36,29 @@ const Notification = ({
return (
-
{notification.text}
+ {notification.type === 'error' && (
+
+ )}
+ {notification.type === 'success' && (
+
+ )}
+ {notification.type === 'info' && (
+
+ )}
+
+ {notification.text}
+
);
diff --git a/frontend/components/context/Notifications/NotificationProvider.tsx b/frontend/components/context/Notifications/NotificationProvider.tsx
index b029dc6c6..05f9eee19 100644
--- a/frontend/components/context/Notifications/NotificationProvider.tsx
+++ b/frontend/components/context/Notifications/NotificationProvider.tsx
@@ -1,8 +1,8 @@
-import { createContext, ReactNode, useContext, useState } from "react";
+import { createContext, ReactNode, useContext, useState } from 'react';
-import Notifications from "./Notifications";
+import Notifications from './Notifications';
-type NotificationType = "success" | "error" | "info";
+type NotificationType = 'success' | 'error' | 'info';
export type Notification = {
text: string;
@@ -15,7 +15,7 @@ type NotificationContextState = {
};
const NotificationContext = createContext({
- createNotification: () => console.log("createNotification not set!"),
+ createNotification: () => console.log('createNotification not set!')
});
export const useNotificationContext = () => useContext(NotificationContext);
@@ -37,8 +37,8 @@ const NotificationProvider = ({ children }: NotificationProviderProps) => {
const createNotification = ({
text,
- type = "success",
- timeoutMs = 2000,
+ type = 'success',
+ timeoutMs = 5000
}: Notification) => {
const doesNotifExist = notifications.some((notif) => notif.text === text);
@@ -54,7 +54,7 @@ const NotificationProvider = ({ children }: NotificationProviderProps) => {
return (
[];
@@ -8,14 +8,14 @@ interface NoticationsProps {
const Notifications = ({
notifications,
- clearNotification,
+ clearNotification
}: NoticationsProps) => {
if (!notifications.length) {
return null;
}
return (
-
+
{notifications.map((notif) => (
{
const clientPublicKey = clientOldPassword.getPublicKey();
@@ -42,13 +42,13 @@ const changePassword = async (
let serverPublicKey, salt;
try {
const res = await SRP1({
- clientPublicKey: clientPublicKey,
+ clientPublicKey: clientPublicKey
});
serverPublicKey = res.serverPublicKey;
salt = res.salt;
} catch (err) {
setCurrentPasswordError(true);
- console.log("Wrong current password", err, 1);
+ console.log('Wrong current password', err, 1);
}
clientOldPassword.setSalt(salt);
@@ -58,27 +58,27 @@ const changePassword = async (
clientNewPassword.init(
{
username: email,
- password: newPassword,
+ password: newPassword
},
async () => {
clientNewPassword.createVerifier(async (err, result) => {
// The Blob part here is needed to account for symbols that count as 2+ bytes (e.g., é, å, ø)
- let { ciphertext, iv, tag } = Aes256Gcm.encrypt(
- localStorage.getItem("PRIVATE_KEY"),
- newPassword
+ const { ciphertext, iv, tag } = Aes256Gcm.encrypt({
+ text: localStorage.getItem('PRIVATE_KEY'),
+ secret: newPassword
.slice(0, 32)
.padStart(
32 +
(newPassword.slice(0, 32).length -
new Blob([newPassword]).size),
- "0"
+ '0'
)
- );
+ });
if (ciphertext) {
- localStorage.setItem("encryptedPrivateKey", ciphertext);
- localStorage.setItem("iv", iv);
- localStorage.setItem("tag", tag);
+ localStorage.setItem('encryptedPrivateKey', ciphertext);
+ localStorage.setItem('iv', iv);
+ localStorage.setItem('tag', tag);
let res;
try {
@@ -88,14 +88,14 @@ const changePassword = async (
tag,
salt: result.salt,
verifier: result.verifier,
- clientProof,
+ clientProof
});
if (res.status == 400) {
setCurrentPasswordError(true);
} else if (res.status == 200) {
setPasswordChanged(true);
- setCurrentPassword("");
- setNewPassword("");
+ setCurrentPassword('');
+ setNewPassword('');
}
} catch (err) {
setCurrentPasswordError(true);
@@ -108,7 +108,7 @@ const changePassword = async (
}
);
} catch (error) {
- console.log("Something went wrong during changing the password");
+ console.log('Something went wrong during changing the password');
}
return true;
};
diff --git a/frontend/components/utilities/cryptography/crypto.ts b/frontend/components/utilities/cryptography/crypto.ts
index a50ee6a0a..409b447fc 100644
--- a/frontend/components/utilities/cryptography/crypto.ts
+++ b/frontend/components/utilities/cryptography/crypto.ts
@@ -1,12 +1,12 @@
-const nacl = require("tweetnacl");
-nacl.util = require("tweetnacl-util");
-const aes = require("./aes-256-gcm");
+const nacl = require('tweetnacl');
+nacl.util = require('tweetnacl-util');
+import aes from './aes-256-gcm';
type encryptAsymmetricProps = {
plaintext: string;
publicKey: string;
privateKey: string;
-}
+};
/**
* Return assymmetrically encrypted [plaintext] using [publicKey] where
@@ -19,7 +19,11 @@ type encryptAsymmetricProps = {
* @returns {String} ciphertext - base64-encoded ciphertext
* @returns {String} nonce - base64-encoded nonce
*/
-const encryptAssymmetric = ({ plaintext, publicKey, privateKey }: encryptAsymmetricProps): object => {
+const encryptAssymmetric = ({
+ plaintext,
+ publicKey,
+ privateKey
+}: encryptAsymmetricProps): object => {
const nonce = nacl.randomBytes(24);
const ciphertext = nacl.box(
nacl.util.decodeUTF8(plaintext),
@@ -30,7 +34,7 @@ const encryptAssymmetric = ({ plaintext, publicKey, privateKey }: encryptAsymmet
return {
ciphertext: nacl.util.encodeBase64(ciphertext),
- nonce: nacl.util.encodeBase64(nonce),
+ nonce: nacl.util.encodeBase64(nonce)
};
};
@@ -39,7 +43,7 @@ type decryptAsymmetricProps = {
nonce: string;
publicKey: string;
privateKey: string;
-}
+};
/**
* Return assymmetrically decrypted [ciphertext] using [privateKey] where
@@ -49,9 +53,13 @@ type decryptAsymmetricProps = {
* @param {String} obj.nonce - nonce
* @param {String} obj.publicKey - base64-encoded public key of the sender
* @param {String} obj.privateKey - base64-encoded private key of the receiver (current user)
- * @param {String} plaintext - UTF8 plaintext
*/
-const decryptAssymmetric = ({ ciphertext, nonce, publicKey, privateKey }: decryptAsymmetricProps): string => {
+const decryptAssymmetric = ({
+ ciphertext,
+ nonce,
+ publicKey,
+ privateKey
+}: decryptAsymmetricProps): string => {
const plaintext = nacl.box.open(
nacl.util.decodeBase64(ciphertext),
nacl.util.decodeBase64(nonce),
@@ -65,7 +73,7 @@ const decryptAssymmetric = ({ ciphertext, nonce, publicKey, privateKey }: decryp
type encryptSymmetricProps = {
plaintext: string;
key: string;
-}
+};
/**
* Return symmetrically encrypted [plaintext] using [key].
@@ -73,15 +81,18 @@ type encryptSymmetricProps = {
* @param {String} obj.plaintext - plaintext to encrypt
* @param {String} obj.key - 16-byte hex key
*/
-const encryptSymmetric = ({ plaintext, key }: encryptSymmetricProps): object => {
+const encryptSymmetric = ({
+ plaintext,
+ key
+}: encryptSymmetricProps): object => {
let ciphertext, iv, tag;
try {
- const obj = aes.encrypt(plaintext, key);
+ const obj = aes.encrypt({ text: plaintext, secret: key });
ciphertext = obj.ciphertext;
iv = obj.iv;
tag = obj.tag;
} catch (err) {
- console.log("Failed to perform encryption");
+ console.log('Failed to perform encryption');
console.log(err);
process.exit(1);
}
@@ -89,7 +100,7 @@ const encryptSymmetric = ({ plaintext, key }: encryptSymmetricProps): object =>
return {
ciphertext,
iv,
- tag,
+ tag
};
};
@@ -98,7 +109,7 @@ type decryptSymmetricProps = {
iv: string;
tag: string;
key: string;
-}
+};
/**
* Return symmetrically decypted [ciphertext] using [iv], [tag],
@@ -110,12 +121,17 @@ type decryptSymmetricProps = {
* @param {String} obj.key - 32-byte hex key
*
*/
-const decryptSymmetric = ({ ciphertext, iv, tag, key }: decryptSymmetricProps): string => {
+const decryptSymmetric = ({
+ ciphertext,
+ iv,
+ tag,
+ key
+}: decryptSymmetricProps): string => {
let plaintext;
try {
- plaintext = aes.decrypt(ciphertext, iv, tag, key);
+ plaintext = aes.decrypt({ ciphertext, iv, tag, secret: key });
} catch (err) {
- console.log("Failed to perform decryption");
+ console.log('Failed to perform decryption');
process.exit(1);
}
@@ -126,5 +142,5 @@ export {
decryptAssymmetric,
decryptSymmetric,
encryptAssymmetric,
- encryptSymmetric,
+ encryptSymmetric
};
diff --git a/frontend/components/utilities/cryptography/issueBackupKey.ts b/frontend/components/utilities/cryptography/issueBackupKey.ts
index 518186406..147377b77 100644
--- a/frontend/components/utilities/cryptography/issueBackupKey.ts
+++ b/frontend/components/utilities/cryptography/issueBackupKey.ts
@@ -1,7 +1,6 @@
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';
@@ -12,21 +11,22 @@ const clientPassword = new jsrp.client();
const clientKey = new jsrp.client();
const crypto = require('crypto');
-interface Props {
+interface BackupKeyProps {
email: string;
password: string;
personalName: string;
- setBackupKeyError: any;
- setBackupKeyIssued: any;
+ setBackupKeyError: (value: boolean) => void;
+ setBackupKeyIssued: (value: boolean) => void;
}
/**
- * 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
+ * This function issue a backup key for a user
+ * @param {obkect} obj
+ * @param {string} obj.email - email of a user issuing a backup key
+ * @param {string} obj.password - password of a user issuing a backup key
+ * @param {string} obj.personalName - name of a user issuing a backup key
+ * @param {function} obj.setBackupKeyError - state function that turns true if there is an erorr with a backup key
+ * @param {function} obj.setBackupKeyIssued - state function that turns true if a backup key was issued correctly
* @returns
*/
const issueBackupKey = async ({
@@ -35,7 +35,7 @@ const issueBackupKey = async ({
personalName,
setBackupKeyError,
setBackupKeyIssued
-}: Props) => {
+}: BackupKeyProps) => {
try {
setBackupKeyError(false);
setBackupKeyIssued(false);
@@ -72,14 +72,11 @@ const issueBackupKey = async ({
},
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
- );
+ async (err: any, result: { salt: string; verifier: string }) => {
+ const { ciphertext, iv, tag } = Aes256Gcm.encrypt({
+ text: String(localStorage.getItem('PRIVATE_KEY')),
+ secret: generatedKey
+ });
const res = await issueBackupPrivateKey({
encryptedPrivateKey: ciphertext,
@@ -90,10 +87,14 @@ const issueBackupKey = async ({
clientProof
});
- if (res && res.status == 400) {
+ if (res?.status == 400) {
setBackupKeyError(true);
- } else if (res && res.status == 200) {
- generateBackupPDF(personalName, email, generatedKey);
+ } else if (res?.status == 200) {
+ generateBackupPDF({
+ personalName,
+ personalEmail: email,
+ generatedKey
+ });
setBackupKeyIssued(true);
}
}
diff --git a/frontend/components/utilities/generateBackupPDF.js b/frontend/components/utilities/generateBackupPDF.ts
similarity index 94%
rename from frontend/components/utilities/generateBackupPDF.js
rename to frontend/components/utilities/generateBackupPDF.ts
index 58e0b6667..d47bdfe73 100644
--- a/frontend/components/utilities/generateBackupPDF.js
+++ b/frontend/components/utilities/generateBackupPDF.ts
@@ -1,86 +1,96 @@
-import { jsPDF } from "jspdf";
+import { jsPDF } from 'jspdf';
+
+interface PDFProps {
+ personalName: string;
+ personalEmail: string;
+ generatedKey: string;
+}
/**
* This function generate a pdf with a secret key for a user.
*/
-function generateBackupPDF(personalName, personalEmail, generatedKey) {
+function generateBackupPDF({
+ personalName,
+ personalEmail,
+ generatedKey
+}: PDFProps) {
const imgData =
- "data:image/png;base64,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";
+ 'data:image/png;base64,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';
// new jsPDF('p', 'mm', [297, 210]);
- var today = new Date();
- var dd = String(today.getDate()).padStart(2, "0");
- var mm = String(today.getMonth() + 1).padStart(2, "0"); //January is 0!
- var yyyy = today.getFullYear();
+ const today = new Date();
+ const dd = String(today.getDate()).padStart(2, '0');
+ const mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0!
+ const yyyy = today.getFullYear();
- today = mm + "/" + dd + "/" + yyyy;
+ const todayFormatted = mm + '/' + dd + '/' + yyyy;
- var doc = new jsPDF("p", "pt");
- doc.setFillColor(13, 17, 23);
- doc.rect(0, 0, 600, 900, "F");
- doc.setTextColor(227, 227, 227);
- doc.addImage(imgData, "png", 30, 35, 535, 72);
- doc.addFont("helvetica", "normal");
+ const doc = new jsPDF('p', 'pt');
+ doc.setFillColor(255, 255, 255);
+ doc.rect(0, 0, 600, 900, 'F');
+ doc.setTextColor(23, 23, 23);
+ doc.addImage(imgData, 'png', 30, 35, 535, 72);
+ doc.addFont('helvetica', 'normal', '');
doc.setFontSize(12);
doc.text(
+ 'Created for ' + personalName + ' on ' + todayFormatted + '.',
290,
130,
- "Created for " + personalName + " on " + today + ".",
- "center"
+ { align: 'center' }
);
doc.setFontSize(14);
doc.text(
+ 'In case you get locked out of you Infisical account, you`ll need these account details',
32,
- 180,
- "In case you get locked out of you Infisical account, you`ll need these account details"
+ 180
);
- doc.text(32, 200, "to sign in —");
- doc.setFont(undefined, "bold");
+ doc.text('to sign in —', 32, 200);
+ doc.setFont('helvetica', 'bold');
doc.text(
+ 'including your Secret Key, which we absolutely cannot access or',
110,
- 200,
- "including your Secret Key, which we absolutely cannot access or"
+ 200
);
- doc.text(32, 220, "recover for you. ");
- doc.setFont(undefined, "normal");
- doc.text(32, 250, "Recommendations:");
+ doc.text('recover for you. ', 32, 220);
+ doc.setFont('helvetica', 'normal');
+ doc.text('Recommendations:', 32, 250);
doc.text(
+ '1. We recommend to get your Emergency Kit off your computer and print a copy.',
32,
- 280,
- "1. We recommend to get your Emergency Kit off your computer and print a copy."
+ 280
);
doc.text(
+ '2. Store it somewhere safe (such as with your birth certificate, your will, or on your',
32,
- 310,
- "2. Store it somewhere safe (such as with your birth certificate, your will, or on your"
+ 310
);
- doc.text(32, 330, "personal cloud storage).");
- doc.setFillColor(206, 217, 111);
- doc.roundedRect(32, 350, 530, 190, 5, 5, "F");
+ doc.text('personal cloud storage).', 32, 330);
+ doc.setFillColor(251, 255, 158);
+ doc.roundedRect(32, 350, 530, 190, 5, 5, 'F');
doc.setDrawColor(228, 255, 0);
doc.setLineWidth(1);
- doc.roundedRect(32, 350, 530, 190, 5, 5, "S");
+ doc.roundedRect(32, 350, 530, 190, 5, 5, 'S');
doc.setTextColor(43, 43, 43);
- doc.setFont(undefined, "bold");
+ doc.setFont('helvetica', 'bold');
doc.setFontSize(15);
- doc.text(290, 375, "Infisical Account Details", "center");
- doc.setFont(undefined, "normal");
+ doc.text('Infisical Account Details', 290, 375, { align: 'center' });
doc.setFontSize(12);
- doc.text(50, 420, "SIGN-IN URL");
- doc.text(50, 465, "EMAIL ADDRESS");
- doc.text(50, 510, "SECRET KEY");
- doc.setFillColor(23, 27, 33);
- doc.roundedRect(170, 398, 375, 35, 5, 5, "F");
- doc.roundedRect(170, 443, 375, 35, 5, 5, "F");
- doc.roundedRect(170, 488, 375, 35, 5, 5, "F");
- doc.setTextColor(227, 227, 227);
+ doc.text('SIGN-IN URL', 50, 420);
+ doc.text('EMAIL ADDRESS', 50, 465);
+ doc.text('SECRET KEY', 50, 510);
+ doc.setFont('helvetica', 'normal');
+ doc.setFillColor(254, 255, 235);
+ doc.roundedRect(170, 398, 375, 35, 5, 5, 'F');
+ doc.roundedRect(170, 443, 375, 35, 5, 5, 'F');
+ doc.roundedRect(170, 488, 375, 35, 5, 5, 'F');
+ doc.setTextColor(23, 23, 23);
doc.setFontSize(14);
- doc.text(180, 420, "https://app.infisical.com/login");
- doc.text(180, 465, personalEmail);
- doc.text(180, 510, generatedKey);
- doc.text(32, 575, "Need help? Contact us at support@infisical.com");
+ doc.text('https://app.infisical.com/login', 180, 420);
+ doc.text(personalEmail, 180, 465);
+ doc.text(generatedKey, 180, 510);
+ doc.text('Need help? Contact us at support@infisical.com', 32, 575);
- doc.save("Infisical Emergency Kit.pdf");
+ doc.save('Infisical Emergency Kit.pdf');
}
export default generateBackupPDF;
diff --git a/frontend/pages/api/auth/CheckAuth.ts b/frontend/pages/api/auth/CheckAuth.ts
index ad754dfb3..2578d7ce9 100644
--- a/frontend/pages/api/auth/CheckAuth.ts
+++ b/frontend/pages/api/auth/CheckAuth.ts
@@ -3,9 +3,6 @@ import SecurityClient from '~/utilities/SecurityClient';
/**
* This function is used to check if the user is authenticated.
* To do that, we get their tokens from cookies, and verify if they are good.
- * @param {*} req
- * @param {*} res
- * @returns
*/
const checkAuth = async () => {
return SecurityClient.fetchCall('/api/v1/auth/checkAuth', {
diff --git a/frontend/pages/api/auth/CheckEmailVerificationCode.ts b/frontend/pages/api/auth/CheckEmailVerificationCode.ts
index 08fb6b391..0709592a3 100644
--- a/frontend/pages/api/auth/CheckEmailVerificationCode.ts
+++ b/frontend/pages/api/auth/CheckEmailVerificationCode.ts
@@ -5,8 +5,9 @@ interface Props {
/**
* This route check the verification code from the email that user just recieved
- * @param {*} email
- * @param {*} code
+ * @param {object} obj
+ * @param {string} obj.email
+ * @param {string} obj.code
* @returns
*/
const checkEmailVerificationCode = ({ email, code }: Props) => {
diff --git a/frontend/pages/api/auth/CompleteAccountInformationSignup.ts b/frontend/pages/api/auth/CompleteAccountInformationSignup.ts
index 98e78dec9..8057e776a 100644
--- a/frontend/pages/api/auth/CompleteAccountInformationSignup.ts
+++ b/frontend/pages/api/auth/CompleteAccountInformationSignup.ts
@@ -15,16 +15,18 @@ interface Props {
/**
* This function is called in the end of the signup process.
* It sends all the necessary nformation to the server.
- * @param {*} email
- * @param {*} firstName
- * @param {*} lastName
- * @param {*} workspace
- * @param {*} publicKey
- * @param {*} ciphertext
- * @param {*} iv
- * @param {*} tag
- * @param {*} salt
- * @param {*} verifier
+ * @param {object} obj
+ * @param {string} obj.email - email of the user completing signup
+ * @param {string} obj.firstName - first name of the user completing signup
+ * @param {string} obj.lastName - last name of the user completing sign up
+ * @param {string} obj.organizationName - organization name for this user (usually, [FIRST_NAME]'s organization)
+ * @param {string} obj.publicKey - public key of the user completing signup
+ * @param {string} obj.ciphertext
+ * @param {string} obj.iv
+ * @param {string} obj.tag
+ * @param {string} obj.salt
+ * @param {string} obj.verifier
+ * @param {string} obj.token - token that confirms a user's identity
* @returns
*/
const completeAccountInformationSignup = ({
diff --git a/frontend/pages/api/auth/CompleteAccountInformationSignupInvite.ts b/frontend/pages/api/auth/CompleteAccountInformationSignupInvite.ts
index 1e5abdc45..03c11cb67 100644
--- a/frontend/pages/api/auth/CompleteAccountInformationSignupInvite.ts
+++ b/frontend/pages/api/auth/CompleteAccountInformationSignupInvite.ts
@@ -14,15 +14,17 @@ interface Props {
/**
* This function is called in the end of the signup process.
* It sends all the necessary nformation to the server.
- * @param {*} email
- * @param {*} firstName
- * @param {*} lastName
- * @param {*} publicKey
- * @param {*} ciphertext
- * @param {*} iv
- * @param {*} tag
- * @param {*} salt
- * @param {*} verifier
+ * @param {object} obj
+ * @param {string} obj.email - email of the user completing signupinvite flow
+ * @param {string} obj.firstName - first name of the user completing signupinvite flow
+ * @param {string} obj.lastName - last name of the user completing signupinvite flow
+ * @param {string} obj.publicKey - public key of the user completing signupinvite flow
+ * @param {string} obj.ciphertext
+ * @param {string} obj.iv
+ * @param {string} obj.tag
+ * @param {string} obj.salt
+ * @param {string} obj.verifier
+ * @param {string} obj.token - token that confirms a user's identity
* @returns
*/
const completeAccountInformationSignupInvite = ({
diff --git a/frontend/pages/api/auth/IssueBackupPrivateKey.ts b/frontend/pages/api/auth/IssueBackupPrivateKey.ts
index 9b300f55b..e24ac510e 100644
--- a/frontend/pages/api/auth/IssueBackupPrivateKey.ts
+++ b/frontend/pages/api/auth/IssueBackupPrivateKey.ts
@@ -11,6 +11,14 @@ interface Props {
/**
* This is the route that issues a backup private key that will afterwards be added into a pdf
+ * @param {object} obj
+ * @param {string} obj.encryptedPrivateKey
+ * @param {string} obj.iv
+ * @param {string} obj.tag
+ * @param {string} obj.salt
+ * @param {string} obj.verifier
+ * @param {string} obj.clientProof
+ * @returns
*/
const issueBackupPrivateKey = ({
encryptedPrivateKey,
diff --git a/frontend/pages/api/auth/SRP1.ts b/frontend/pages/api/auth/SRP1.ts
index 292dcbdd1..cb6386ff2 100644
--- a/frontend/pages/api/auth/SRP1.ts
+++ b/frontend/pages/api/auth/SRP1.ts
@@ -6,7 +6,7 @@ interface Props {
/**
* This is the first step of the change password process (pake)
- * @param {*} clientPublicKey
+ * @param {string} clientPublicKey
* @returns
*/
const SRP1 = ({ clientPublicKey }: Props) => {
diff --git a/frontend/pages/api/auth/VerifySignupInvite.ts b/frontend/pages/api/auth/VerifySignupInvite.ts
index 20e52dfd1..0b6cc7577 100644
--- a/frontend/pages/api/auth/VerifySignupInvite.ts
+++ b/frontend/pages/api/auth/VerifySignupInvite.ts
@@ -5,8 +5,9 @@ interface Props {
/**
* This route verifies the signup invite link
- * @param {*} email
- * @param {*} code
+ * @param {object} obj
+ * @param {string} obj.email - email that a user is trying to verify
+ * @param {string} obj.code - code that a user received to the abovementioned email
* @returns
*/
const verifySignupInvite = ({ email, code }: Props) => {
diff --git a/frontend/pages/api/files/GetSecrets.ts b/frontend/pages/api/files/GetSecrets.ts
index b8a116175..8ff22b57c 100644
--- a/frontend/pages/api/files/GetSecrets.ts
+++ b/frontend/pages/api/files/GetSecrets.ts
@@ -2,8 +2,8 @@ import SecurityClient from '~/utilities/SecurityClient';
/**
* This function fetches the encrypted secrets from the .env file
- * @param {*} workspaceId
- * @param {*} env
+ * @param {string} workspaceId - project is for which a user is trying to get secrets
+ * @param {string} env - environment of a project for which a user is trying ot get secrets
* @returns
*/
const getSecrets = async (workspaceId: string, env: string) => {
diff --git a/frontend/pages/api/files/UploadSecrets.ts b/frontend/pages/api/files/UploadSecrets.ts
index 3644778fb..04fcb78b5 100644
--- a/frontend/pages/api/files/UploadSecrets.ts
+++ b/frontend/pages/api/files/UploadSecrets.ts
@@ -9,8 +9,11 @@ interface Props {
/**
* This function uploads the encrypted .env file
- * @param {*} req
- * @param {*} res
+ * @param {object} obj
+ * @param {string} obj.workspaceId
+ * @param {} obj.secrets
+ * @param {} obj.keys
+ * @param {string} obj.environment
* @returns
*/
const uploadSecrets = async ({
diff --git a/frontend/pages/api/integrations/authorizeIntegration.ts b/frontend/pages/api/integrations/authorizeIntegration.ts
index 83158f594..1454bde4d 100644
--- a/frontend/pages/api/integrations/authorizeIntegration.ts
+++ b/frontend/pages/api/integrations/authorizeIntegration.ts
@@ -7,7 +7,10 @@ interface Props {
}
/**
* This is the first step of the change password process (pake)
- * @param {*} clientPublicKey
+ * @param {object} obj
+ * @param {object} obj.workspaceId - project id for which we want to authorize the integration
+ * @param {object} obj.code
+ * @param {object} obj.integration - integration which a user is trying to turn on
* @returns
*/
const AuthorizeIntegration = ({ workspaceId, code, integration }: Props) => {
diff --git a/frontend/pages/dashboard/[id].js b/frontend/pages/dashboard/[id].js
index 050193b1b..7a9522a60 100644
--- a/frontend/pages/dashboard/[id].js
+++ b/frontend/pages/dashboard/[id].js
@@ -385,14 +385,14 @@ export default function Dashboard() {
if (nameErrors) {
return createNotification({
- text: 'Solve all name errors first!',
+ text: 'Solve all name errors before saving secrets.',
type: 'error'
});
}
if (duplicatesExist) {
return createNotification({
- text: "Your secrets weren't saved; please fix the conflicts first.",
+ text: 'Remove duplicated secret names before saving.',
type: 'error'
});
}
diff --git a/frontend/pages/home/[id].tsx b/frontend/pages/home/[id].tsx
index c67b798af..d433600d3 100644
--- a/frontend/pages/home/[id].tsx
+++ b/frontend/pages/home/[id].tsx
@@ -47,7 +47,7 @@ const learningItem = ({
>
{
- if (userAction) {
+ if (userAction && userAction != 'first_time_secrets_pushed') {
await registerUserAction({
action: userAction
});
diff --git a/frontend/pages/signup.tsx b/frontend/pages/signup.tsx
index 77015ab75..8991dc867 100644
--- a/frontend/pages/signup.tsx
+++ b/frontend/pages/signup.tsx
@@ -1,6 +1,5 @@
-import React, { useEffect, useRef, useState } from 'react';
+import React, { useEffect, useState } from 'react';
import ReactCodeInput from 'react-code-input';
-import dynamic from 'next/dynamic';
import Head from 'next/head';
import Image from 'next/image';
import Link from 'next/link';
@@ -181,15 +180,15 @@ export default function SignUp() {
const PRIVATE_KEY = nacl.util.encodeBase64(secretKeyUint8Array);
const PUBLIC_KEY = nacl.util.encodeBase64(publicKeyUint8Array);
- const { ciphertext, iv, tag } = Aes256Gcm.encrypt(
- PRIVATE_KEY,
- password
+ const { ciphertext, iv, tag } = Aes256Gcm.encrypt({
+ text: PRIVATE_KEY,
+ secret: password
.slice(0, 32)
.padStart(
32 + (password.slice(0, 32).length - new Blob([password]).size),
'0'
)
- ) as { ciphertext: string; iv: string; tag: string };
+ }) as { ciphertext: string; iv: string; tag: string };
localStorage.setItem('PRIVATE_KEY', PRIVATE_KEY);
diff --git a/frontend/pages/signupinvite.js b/frontend/pages/signupinvite.js
index c8a8397d7..26b6e1544 100644
--- a/frontend/pages/signupinvite.js
+++ b/frontend/pages/signupinvite.js
@@ -1,38 +1,38 @@
-import React, { useState } from "react";
-import Head from "next/head";
-import Image from "next/image";
-import Link from "next/link";
-import { useRouter } from "next/router";
-import { faCheck, faWarning, faX } from "@fortawesome/free-solid-svg-icons";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import React, { useState } from 'react';
+import Head from 'next/head';
+import Image from 'next/image';
+import Link from 'next/link';
+import { useRouter } from 'next/router';
+import { faCheck, faWarning, faX } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import Button from "~/components/basic/buttons/Button";
-import InputField from "~/components/basic/InputField";
-import Aes256Gcm from "~/components/utilities/cryptography/aes-256-gcm";
-import issueBackupKey from "~/components/utilities/cryptography/issueBackupKey";
-import attemptLogin from "~/utilities/attemptLogin";
-import passwordCheck from "~/utilities/checks/PasswordCheck";
+import Button from '~/components/basic/buttons/Button';
+import InputField from '~/components/basic/InputField';
+import Aes256Gcm from '~/components/utilities/cryptography/aes-256-gcm';
+import issueBackupKey from '~/components/utilities/cryptography/issueBackupKey';
+import attemptLogin from '~/utilities/attemptLogin';
+import passwordCheck from '~/utilities/checks/PasswordCheck';
-import completeAccountInformationSignupInvite from "./api/auth/CompleteAccountInformationSignupInvite";
-import verifySignupInvite from "./api/auth/VerifySignupInvite";
+import completeAccountInformationSignupInvite from './api/auth/CompleteAccountInformationSignupInvite';
+import verifySignupInvite from './api/auth/VerifySignupInvite';
-const nacl = require("tweetnacl");
-const jsrp = require("jsrp");
-nacl.util = require("tweetnacl-util");
+const nacl = require('tweetnacl');
+const jsrp = require('jsrp');
+nacl.util = require('tweetnacl-util');
const client = new jsrp.client();
-const queryString = require("query-string");
+const queryString = require('query-string');
export default function SignupInvite() {
- const [password, setPassword] = useState("");
- const [firstName, setFirstName] = useState("");
- const [lastName, setLastName] = useState("");
+ const [password, setPassword] = useState('');
+ const [firstName, setFirstName] = useState('');
+ const [lastName, setLastName] = useState('');
const [firstNameError, setFirstNameError] = useState(false);
const [lastNameError, setLastNameError] = useState(false);
const [passwordErrorLength, setPasswordErrorLength] = useState(false);
const [passwordErrorNumber, setPasswordErrorNumber] = useState(false);
const [passwordErrorLowerCase, setPasswordErrorLowerCase] = useState(false);
const router = useRouter();
- const parsedUrl = queryString.parse(router.asPath.split("?")[1]);
+ const parsedUrl = queryString.parse(router.asPath.split('?')[1]);
const [email, setEmail] = useState(parsedUrl.to);
const token = parsedUrl.token;
const [errorLogin, setErrorLogin] = useState(false);
@@ -74,21 +74,22 @@ export default function SignupInvite() {
const PRIVATE_KEY = nacl.util.encodeBase64(secretKeyUint8Array);
const PUBLIC_KEY = nacl.util.encodeBase64(publicKeyUint8Array);
- const { ciphertext, iv, tag } = Aes256Gcm.encrypt(
- PRIVATE_KEY,
- password
+ const { ciphertext, iv, tag } = Aes256Gcm.encrypt({
+ text: PRIVATE_KEY,
+ secret: password
.slice(0, 32)
.padStart(
32 + (password.slice(0, 32).length - new Blob([password]).size),
- "0"
+ '0'
)
- );
- localStorage.setItem("PRIVATE_KEY", PRIVATE_KEY);
+ });
+
+ localStorage.setItem('PRIVATE_KEY', PRIVATE_KEY);
client.init(
{
username: email,
- password: password,
+ password: password
},
async () => {
client.createVerifier(async (err, result) => {
@@ -102,17 +103,17 @@ export default function SignupInvite() {
tag,
salt: result.salt,
verifier: result.verifier,
- token: verificationToken,
+ token: verificationToken
});
// if everything works, go the main dashboard page.
- if (!errorCheck && response.status == "200") {
+ if (!errorCheck && response.status == '200') {
response = await response.json();
- localStorage.setItem("publicKey", PUBLIC_KEY);
- localStorage.setItem("encryptedPrivateKey", ciphertext);
- localStorage.setItem("iv", iv);
- localStorage.setItem("tag", tag);
+ localStorage.setItem('publicKey', PUBLIC_KEY);
+ localStorage.setItem('encryptedPrivateKey', ciphertext);
+ localStorage.setItem('iv', iv);
+ localStorage.setItem('tag', tag);
try {
await attemptLogin(
@@ -126,7 +127,7 @@ export default function SignupInvite() {
setStep(3);
} catch (error) {
setIsLoading(false);
- console.log("Error", error);
+ console.log('Error', error);
}
}
});
@@ -155,14 +156,14 @@ export default function SignupInvite() {
onButtonPressed={async () => {
const response = await verifySignupInvite({
email,
- code: token,
+ code: token
});
if (response.status == 200) {
setVerificationToken((await response.json()).token);
setStep(2);
} else {
- console.log("ERROR", response);
- router.push("/requestnewinvite");
+ console.log('ERROR', response);
+ router.push('/requestnewinvite');
}
}}
size="lg"
@@ -211,7 +212,7 @@ export default function SignupInvite() {
setPasswordErrorLength,
setPasswordErrorNumber,
setPasswordErrorLowerCase,
- currentErrorCheck: false,
+ currentErrorCheck: false
});
}}
type="password"
@@ -244,7 +245,7 @@ export default function SignupInvite() {
)}
14 characters
@@ -264,7 +265,7 @@ export default function SignupInvite() {
)}
1 lowercase character
@@ -284,7 +285,7 @@ export default function SignupInvite() {
)}
1 number
@@ -335,11 +336,11 @@ export default function SignupInvite() {
await issueBackupKey({
email,
password,
- personalName: firstName + " " + lastName,
+ personalName: firstName + ' ' + lastName,
setBackupKeyError,
- setBackupKeyIssued,
+ setBackupKeyIssued
});
- router.push("/dashboard/");
+ router.push('/dashboard/');
}}
size="lg"
/>