mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 21:27:31 +00:00
Fix merge conflicts
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
@@ -45,7 +44,6 @@ declare module 'jsonwebtoken' {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const login1 = async (req: Request, res: Response) => {
|
export const login1 = async (req: Request, res: Response) => {
|
||||||
try {
|
|
||||||
const {
|
const {
|
||||||
email,
|
email,
|
||||||
clientPublicKey
|
clientPublicKey
|
||||||
@@ -79,13 +77,6 @@ export const login1 = async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to start authentication process'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,11 +87,10 @@ 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 {
|
|
||||||
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 +devices');
|
}).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');
|
||||||
|
|
||||||
@@ -171,13 +161,6 @@ export const login2 = async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to authenticate. Try again?'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -187,8 +170,6 @@ 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 {
|
|
||||||
|
|
||||||
if (req.authData.authMode === AUTH_MODE_JWT && req.authData.authPayload instanceof User && req.authData.tokenVersionId) {
|
if (req.authData.authMode === AUTH_MODE_JWT && req.authData.authPayload instanceof User && req.authData.tokenVersionId) {
|
||||||
await clearTokens(req.authData.tokenVersionId)
|
await clearTokens(req.authData.tokenVersionId)
|
||||||
}
|
}
|
||||||
@@ -213,14 +194,6 @@ export const logout = async (req: Request, res: Response) => {
|
|||||||
ipAddress: req.realIP
|
ipAddress: req.realIP
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to logout'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Successfully logged out.'
|
message: 'Successfully logged out.'
|
||||||
});
|
});
|
||||||
@@ -269,7 +242,6 @@ 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 {
|
|
||||||
const refreshToken = req.cookies.jid;
|
const refreshToken = req.cookies.jid;
|
||||||
|
|
||||||
if (!refreshToken) {
|
if (!refreshToken) {
|
||||||
@@ -311,13 +283,6 @@ export const getNewToken = async (req: Request, res: Response) => {
|
|||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
token
|
token
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Invalid request'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const handleAuthProviderCallback = (req: Request, res: Response) => {
|
export const handleAuthProviderCallback = (req: Request, res: Response) => {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { Types } from 'mongoose';
|
import { Types } from 'mongoose';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Bot, BotKey } from '../../models';
|
import { Bot, BotKey } from '../../models';
|
||||||
import { createBot } from '../../helpers/bot';
|
import { createBot } from '../../helpers/bot';
|
||||||
|
|
||||||
@@ -17,11 +16,9 @@ interface BotKey {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getBotByWorkspaceId = async (req: Request, res: Response) => {
|
export const getBotByWorkspaceId = async (req: Request, res: Response) => {
|
||||||
let bot;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
|
|
||||||
bot = await Bot.findOne({
|
let bot = await Bot.findOne({
|
||||||
workspace: workspaceId
|
workspace: workspaceId
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -33,13 +30,6 @@ export const getBotByWorkspaceId = async (req: Request, res: Response) => {
|
|||||||
workspaceId: new Types.ObjectId(workspaceId)
|
workspaceId: new Types.ObjectId(workspaceId)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to get bot for workspace'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
bot
|
bot
|
||||||
@@ -53,8 +43,6 @@ export const getBotByWorkspaceId = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const setBotActiveState = async (req: Request, res: Response) => {
|
export const setBotActiveState = async (req: Request, res: Response) => {
|
||||||
let bot;
|
|
||||||
try {
|
|
||||||
const { isActive, botKey }: { isActive: boolean, botKey: BotKey } = req.body;
|
const { isActive, botKey }: { isActive: boolean, botKey: BotKey } = req.body;
|
||||||
|
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
@@ -84,7 +72,7 @@ export const setBotActiveState = async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bot = await Bot.findOneAndUpdate({
|
let bot = await Bot.findOneAndUpdate({
|
||||||
_id: req.bot._id
|
_id: req.bot._id
|
||||||
}, {
|
}, {
|
||||||
isActive
|
isActive
|
||||||
@@ -94,14 +82,6 @@ export const setBotActiveState = async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
if (!bot) throw new Error('Failed to update bot active state');
|
if (!bot) throw new Error('Failed to update bot active state');
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to update bot active state'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
bot
|
bot
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { Types } from 'mongoose';
|
import { Types } from 'mongoose';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import {
|
import {
|
||||||
IntegrationAuth,
|
IntegrationAuth,
|
||||||
Bot
|
Bot
|
||||||
@@ -22,21 +21,12 @@ import { standardRequest } from '../../config/request';
|
|||||||
* Return integration authorization with id [integrationAuthId]
|
* Return integration authorization with id [integrationAuthId]
|
||||||
*/
|
*/
|
||||||
export const getIntegrationAuth = async (req: Request, res: Response) => {
|
export const getIntegrationAuth = async (req: Request, res: Response) => {
|
||||||
let integrationAuth;
|
|
||||||
try {
|
|
||||||
const { integrationAuthId } = req.params;
|
const { integrationAuthId } = req.params;
|
||||||
integrationAuth = await IntegrationAuth.findById(integrationAuthId);
|
const integrationAuth = await IntegrationAuth.findById(integrationAuthId);
|
||||||
|
|
||||||
if (!integrationAuth) return res.status(400).send({
|
if (!integrationAuth) return res.status(400).send({
|
||||||
message: 'Failed to find integration authorization'
|
message: 'Failed to find integration authorization'
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to get integration authorization'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
integrationAuth
|
integrationAuth
|
||||||
@@ -61,7 +51,6 @@ export const oAuthExchange = async (
|
|||||||
req: Request,
|
req: Request,
|
||||||
res: Response
|
res: Response
|
||||||
) => {
|
) => {
|
||||||
try {
|
|
||||||
const { workspaceId, code, integration } = req.body;
|
const { workspaceId, code, integration } = req.body;
|
||||||
if (!INTEGRATION_SET.has(integration))
|
if (!INTEGRATION_SET.has(integration))
|
||||||
throw new Error('Failed to validate integration');
|
throw new Error('Failed to validate integration');
|
||||||
@@ -81,13 +70,6 @@ export const oAuthExchange = async (
|
|||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
integrationAuth
|
integrationAuth
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to get OAuth2 code-token exchange'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,7 +86,6 @@ export const saveIntegrationAccessToken = async (
|
|||||||
// TODO: check if access token is valid for each integration
|
// TODO: check if access token is valid for each integration
|
||||||
|
|
||||||
let integrationAuth;
|
let integrationAuth;
|
||||||
try {
|
|
||||||
const {
|
const {
|
||||||
workspaceId,
|
workspaceId,
|
||||||
accessId,
|
accessId,
|
||||||
@@ -146,13 +127,6 @@ export const saveIntegrationAccessToken = async (
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!integrationAuth) throw new Error('Failed to save integration access token');
|
if (!integrationAuth) throw new Error('Failed to save integration access token');
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to save access token for integration'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
integrationAuth
|
integrationAuth
|
||||||
@@ -166,22 +140,13 @@ export const saveIntegrationAccessToken = async (
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getIntegrationAuthApps = async (req: Request, res: Response) => {
|
export const getIntegrationAuthApps = async (req: Request, res: Response) => {
|
||||||
let apps;
|
|
||||||
try {
|
|
||||||
const teamId = req.query.teamId as string;
|
const teamId = req.query.teamId as string;
|
||||||
|
|
||||||
apps = await getApps({
|
const apps = await getApps({
|
||||||
integrationAuth: req.integrationAuth,
|
integrationAuth: req.integrationAuth,
|
||||||
accessToken: req.accessToken,
|
accessToken: req.accessToken,
|
||||||
...teamId && { teamId }
|
...teamId && { teamId }
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to get integration authorization applications",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
apps
|
apps
|
||||||
@@ -402,19 +367,10 @@ export const getIntegrationAuthRailwayServices = async (req: Request, res: Respo
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const deleteIntegrationAuth = async (req: Request, res: Response) => {
|
export const deleteIntegrationAuth = async (req: Request, res: Response) => {
|
||||||
let integrationAuth;
|
const integrationAuth = await revokeAccess({
|
||||||
try {
|
|
||||||
integrationAuth = await revokeAccess({
|
|
||||||
integrationAuth: req.integrationAuth,
|
integrationAuth: req.integrationAuth,
|
||||||
accessToken: req.accessToken,
|
accessToken: req.accessToken,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to delete integration authorization",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
integrationAuth,
|
integrationAuth,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { Types } from 'mongoose';
|
import { Types } from 'mongoose';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import {
|
import {
|
||||||
Integration
|
Integration
|
||||||
} from '../../models';
|
} from '../../models';
|
||||||
@@ -14,9 +13,6 @@ import { eventPushSecrets } from '../../events';
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const createIntegration = async (req: Request, res: Response) => {
|
export const createIntegration = async (req: Request, res: Response) => {
|
||||||
let integration;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const {
|
const {
|
||||||
integrationAuthId,
|
integrationAuthId,
|
||||||
app,
|
app,
|
||||||
@@ -35,7 +31,7 @@ export const createIntegration = async (req: Request, res: Response) => {
|
|||||||
// TODO: validate [sourceEnvironment] and [targetEnvironment]
|
// TODO: validate [sourceEnvironment] and [targetEnvironment]
|
||||||
|
|
||||||
// initialize new integration after saving integration access token
|
// initialize new integration after saving integration access token
|
||||||
integration = await new Integration({
|
const integration = await new Integration({
|
||||||
workspace: req.integrationAuth.workspace._id,
|
workspace: req.integrationAuth.workspace._id,
|
||||||
environment: sourceEnvironment,
|
environment: sourceEnvironment,
|
||||||
isActive,
|
isActive,
|
||||||
@@ -61,15 +57,6 @@ export const createIntegration = async (req: Request, res: Response) => {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to create integration'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
integration,
|
integration,
|
||||||
});
|
});
|
||||||
@@ -82,12 +69,10 @@ export const createIntegration = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const updateIntegration = async (req: Request, res: Response) => {
|
export const updateIntegration = async (req: Request, res: Response) => {
|
||||||
let integration;
|
|
||||||
|
|
||||||
// TODO: add integration-specific validation to ensure that each
|
// TODO: add integration-specific validation to ensure that each
|
||||||
// integration has the correct fields populated in [Integration]
|
// integration has the correct fields populated in [Integration]
|
||||||
|
|
||||||
try {
|
|
||||||
const {
|
const {
|
||||||
environment,
|
environment,
|
||||||
isActive,
|
isActive,
|
||||||
@@ -97,7 +82,7 @@ export const updateIntegration = async (req: Request, res: Response) => {
|
|||||||
owner, // github-specific integration param
|
owner, // github-specific integration param
|
||||||
} = req.body;
|
} = req.body;
|
||||||
|
|
||||||
integration = await Integration.findOneAndUpdate(
|
const integration = await Integration.findOneAndUpdate(
|
||||||
{
|
{
|
||||||
_id: req.integration._id,
|
_id: req.integration._id,
|
||||||
},
|
},
|
||||||
@@ -123,13 +108,6 @@ export const updateIntegration = async (req: Request, res: Response) => {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to update integration",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
integration,
|
integration,
|
||||||
@@ -144,22 +122,13 @@ export const updateIntegration = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const deleteIntegration = async (req: Request, res: Response) => {
|
export const deleteIntegration = async (req: Request, res: Response) => {
|
||||||
let integration;
|
|
||||||
try {
|
|
||||||
const { integrationId } = req.params;
|
const { integrationId } = req.params;
|
||||||
|
|
||||||
integration = await Integration.findOneAndDelete({
|
const integration = await Integration.findOneAndDelete({
|
||||||
_id: integrationId,
|
_id: integrationId,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!integration) throw new Error("Failed to find integration");
|
if (!integration) throw new Error("Failed to find integration");
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to delete integration",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
integration,
|
integration,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Key } from '../../models';
|
import { Key } from '../../models';
|
||||||
import { findMembership } from '../../helpers/membership';
|
import { findMembership } from '../../helpers/membership';
|
||||||
|
|
||||||
@@ -11,7 +10,6 @@ import { findMembership } from '../../helpers/membership';
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const uploadKey = async (req: Request, res: Response) => {
|
export const uploadKey = async (req: Request, res: Response) => {
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
const { key } = req.body;
|
const { key } = req.body;
|
||||||
|
|
||||||
@@ -32,13 +30,6 @@ export const uploadKey = async (req: Request, res: Response) => {
|
|||||||
receiver: key.userId,
|
receiver: key.userId,
|
||||||
workspace: workspaceId
|
workspace: workspaceId
|
||||||
}).save();
|
}).save();
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to upload key to workspace'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Successfully uploaded key to workspace'
|
message: 'Successfully uploaded key to workspace'
|
||||||
@@ -52,25 +43,16 @@ export const uploadKey = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getLatestKey = async (req: Request, res: Response) => {
|
export const getLatestKey = async (req: Request, res: Response) => {
|
||||||
let latestKey;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
|
|
||||||
// get latest key
|
// get latest key
|
||||||
latestKey = await Key.find({
|
const latestKey = await Key.find({
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
receiver: req.user._id
|
receiver: req.user._id
|
||||||
})
|
})
|
||||||
.sort({ createdAt: -1 })
|
.sort({ createdAt: -1 })
|
||||||
.limit(1)
|
.limit(1)
|
||||||
.populate('sender', '+publicKey');
|
.populate('sender', '+publicKey');
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to get latest key'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const resObj: any = {};
|
const resObj: any = {};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { Membership, MembershipOrg, User, Key } from '../../models';
|
import { Membership, MembershipOrg, User, Key } from '../../models';
|
||||||
import {
|
import {
|
||||||
@@ -16,9 +15,7 @@ import { getSiteURL } from '../../config';
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const validateMembership = async (req: Request, res: Response) => {
|
export const validateMembership = async (req: Request, res: Response) => {
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
|
|
||||||
// validate membership
|
// validate membership
|
||||||
const membership = await findMembership({
|
const membership = await findMembership({
|
||||||
user: req.user._id,
|
user: req.user._id,
|
||||||
@@ -28,13 +25,6 @@ export const validateMembership = async (req: Request, res: Response) => {
|
|||||||
if (!membership) {
|
if (!membership) {
|
||||||
throw new Error('Failed to validate membership');
|
throw new Error('Failed to validate membership');
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed workspace connection check'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Workspace membership confirmed'
|
message: 'Workspace membership confirmed'
|
||||||
@@ -48,8 +38,6 @@ export const validateMembership = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const deleteMembership = async (req: Request, res: Response) => {
|
export const deleteMembership = async (req: Request, res: Response) => {
|
||||||
let deletedMembership;
|
|
||||||
try {
|
|
||||||
const { membershipId } = req.params;
|
const { membershipId } = req.params;
|
||||||
|
|
||||||
// check if membership to delete exists
|
// check if membership to delete exists
|
||||||
@@ -80,16 +68,9 @@ export const deleteMembership = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// delete workspace membership
|
// delete workspace membership
|
||||||
deletedMembership = await deleteMember({
|
const deletedMembership = await deleteMember({
|
||||||
membershipId: membershipToDelete._id.toString()
|
membershipId: membershipToDelete._id.toString()
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to delete membership'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
deletedMembership
|
deletedMembership
|
||||||
@@ -103,8 +84,6 @@ export const deleteMembership = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const changeMembershipRole = async (req: Request, res: Response) => {
|
export const changeMembershipRole = async (req: Request, res: Response) => {
|
||||||
let membershipToChangeRole;
|
|
||||||
try {
|
|
||||||
const { membershipId } = req.params;
|
const { membershipId } = req.params;
|
||||||
const { role } = req.body;
|
const { role } = req.body;
|
||||||
|
|
||||||
@@ -113,7 +92,7 @@ export const changeMembershipRole = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validate target membership
|
// validate target membership
|
||||||
membershipToChangeRole = await findMembership({
|
const membershipToChangeRole = await findMembership({
|
||||||
_id: membershipId
|
_id: membershipId
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -139,13 +118,6 @@ export const changeMembershipRole = async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
membershipToChangeRole.role = role;
|
membershipToChangeRole.role = role;
|
||||||
await membershipToChangeRole.save();
|
await membershipToChangeRole.save();
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to change membership role'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
membership: membershipToChangeRole
|
membership: membershipToChangeRole
|
||||||
@@ -159,12 +131,10 @@ export const changeMembershipRole = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const inviteUserToWorkspace = async (req: Request, res: Response) => {
|
export const inviteUserToWorkspace = async (req: Request, res: Response) => {
|
||||||
let invitee, latestKey;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
const { email }: { email: string } = req.body;
|
const { email }: { email: string } = req.body;
|
||||||
|
|
||||||
invitee = await User.findOne({
|
const invitee = await User.findOne({
|
||||||
email
|
email
|
||||||
}).select('+publicKey');
|
}).select('+publicKey');
|
||||||
|
|
||||||
@@ -193,7 +163,7 @@ export const inviteUserToWorkspace = async (req: Request, res: Response) => {
|
|||||||
throw new Error("Failed to validate invitee's organization membership");
|
throw new Error("Failed to validate invitee's organization membership");
|
||||||
|
|
||||||
// get latest key
|
// get latest key
|
||||||
latestKey = await Key.findOne({
|
const latestKey = await Key.findOne({
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
receiver: req.user._id
|
receiver: req.user._id
|
||||||
})
|
})
|
||||||
@@ -218,13 +188,6 @@ export const inviteUserToWorkspace = async (req: Request, res: Response) => {
|
|||||||
callback_url: (await getSiteURL()) + '/login'
|
callback_url: (await getSiteURL()) + '/login'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to invite user to workspace'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
invitee,
|
invitee,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Types } from 'mongoose';
|
import { Types } from 'mongoose';
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { MembershipOrg, Organization, User } from '../../models';
|
import { MembershipOrg, Organization, User } from '../../models';
|
||||||
import { deleteMembershipOrg as deleteMemberFromOrg } from '../../helpers/membershipOrg';
|
import { deleteMembershipOrg as deleteMemberFromOrg } from '../../helpers/membershipOrg';
|
||||||
import { createToken } from '../../helpers/auth';
|
import { createToken } from '../../helpers/auth';
|
||||||
@@ -19,12 +18,10 @@ import { validateUserEmail } from '../../validation';
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const deleteMembershipOrg = async (req: Request, res: Response) => {
|
export const deleteMembershipOrg = async (req: Request, res: Response) => {
|
||||||
let membershipOrgToDelete;
|
|
||||||
try {
|
|
||||||
const { membershipOrgId } = req.params;
|
const { membershipOrgId } = req.params;
|
||||||
|
|
||||||
// check if organization membership to delete exists
|
// check if organization membership to delete exists
|
||||||
membershipOrgToDelete = await MembershipOrg.findOne({
|
const membershipOrgToDelete = await MembershipOrg.findOne({
|
||||||
_id: membershipOrgId
|
_id: membershipOrgId
|
||||||
}).populate('user');
|
}).populate('user');
|
||||||
|
|
||||||
@@ -58,13 +55,6 @@ export const deleteMembershipOrg = async (req: Request, res: Response) => {
|
|||||||
await updateSubscriptionOrgQuantity({
|
await updateSubscriptionOrgQuantity({
|
||||||
organizationId: membershipOrg.organization.toString()
|
organizationId: membershipOrg.organization.toString()
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to delete organization membership'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return membershipOrgToDelete;
|
return membershipOrgToDelete;
|
||||||
};
|
};
|
||||||
@@ -80,14 +70,6 @@ export const changeMembershipOrgRole = async (req: Request, res: Response) => {
|
|||||||
// [membershipOrgId]
|
// [membershipOrgId]
|
||||||
|
|
||||||
let membershipToChangeRole;
|
let membershipToChangeRole;
|
||||||
// try {
|
|
||||||
// } catch (err) {
|
|
||||||
// Sentry.setUser({ email: req.user.email });
|
|
||||||
// Sentry.captureException(err);
|
|
||||||
// return res.status(400).send({
|
|
||||||
// message: 'Failed to change organization membership role'
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
membershipOrg: membershipToChangeRole
|
membershipOrg: membershipToChangeRole
|
||||||
@@ -103,7 +85,6 @@ export const changeMembershipOrgRole = async (req: Request, res: Response) => {
|
|||||||
*/
|
*/
|
||||||
export const inviteUserToOrganization = async (req: Request, res: Response) => {
|
export const inviteUserToOrganization = async (req: Request, res: Response) => {
|
||||||
let invitee, inviteeMembershipOrg, completeInviteLink;
|
let invitee, inviteeMembershipOrg, completeInviteLink;
|
||||||
try {
|
|
||||||
const { organizationId, inviteeEmail } = req.body;
|
const { organizationId, inviteeEmail } = req.body;
|
||||||
const host = req.headers.host;
|
const host = req.headers.host;
|
||||||
const siteUrl = `${req.protocol}://${host}`;
|
const siteUrl = `${req.protocol}://${host}`;
|
||||||
@@ -212,13 +193,6 @@ export const inviteUserToOrganization = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await updateSubscriptionOrgQuantity({ organizationId });
|
await updateSubscriptionOrgQuantity({ organizationId });
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to send organization invite'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: `Sent an invite link to ${req.body.inviteeEmail}`,
|
message: `Sent an invite link to ${req.body.inviteeEmail}`,
|
||||||
@@ -234,8 +208,7 @@ export const inviteUserToOrganization = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const verifyUserToOrganization = async (req: Request, res: Response) => {
|
export const verifyUserToOrganization = async (req: Request, res: Response) => {
|
||||||
let user, token;
|
let user;
|
||||||
try {
|
|
||||||
const {
|
const {
|
||||||
email,
|
email,
|
||||||
organizationId,
|
organizationId,
|
||||||
@@ -284,20 +257,13 @@ export const verifyUserToOrganization = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// generate temporary signup token
|
// generate temporary signup token
|
||||||
token = createToken({
|
const token = createToken({
|
||||||
payload: {
|
payload: {
|
||||||
userId: user._id.toString()
|
userId: user._id.toString()
|
||||||
},
|
},
|
||||||
expiresIn: await getJwtSignupLifetime(),
|
expiresIn: await getJwtSignupLifetime(),
|
||||||
secret: await getJwtSignupSecret()
|
secret: await getJwtSignupSecret()
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
error: 'Failed email magic link verification for organization invitation'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Successfully verified email',
|
message: 'Successfully verified email',
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import Stripe from 'stripe';
|
import Stripe from 'stripe';
|
||||||
import {
|
import {
|
||||||
@@ -15,21 +14,12 @@ import _ from 'lodash';
|
|||||||
import { getStripeSecretKey, getSiteURL } from '../../config';
|
import { getStripeSecretKey, getSiteURL } from '../../config';
|
||||||
|
|
||||||
export const getOrganizations = async (req: Request, res: Response) => {
|
export const getOrganizations = async (req: Request, res: Response) => {
|
||||||
let organizations;
|
const organizations = (
|
||||||
try {
|
|
||||||
organizations = (
|
|
||||||
await MembershipOrg.find({
|
await MembershipOrg.find({
|
||||||
user: req.user._id,
|
user: req.user._id,
|
||||||
status: ACCEPTED
|
status: ACCEPTED
|
||||||
}).populate('organization')
|
}).populate('organization')
|
||||||
).map((m) => m.organization);
|
).map((m) => m.organization);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to get organizations'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
organizations
|
organizations
|
||||||
@@ -44,8 +34,6 @@ export const getOrganizations = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const createOrganization = async (req: Request, res: Response) => {
|
export const createOrganization = async (req: Request, res: Response) => {
|
||||||
let organization;
|
|
||||||
try {
|
|
||||||
const { organizationName } = req.body;
|
const { organizationName } = req.body;
|
||||||
|
|
||||||
if (organizationName.length < 1) {
|
if (organizationName.length < 1) {
|
||||||
@@ -53,7 +41,7 @@ export const createOrganization = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create organization and add user as member
|
// create organization and add user as member
|
||||||
organization = await create({
|
const organization = await create({
|
||||||
email: req.user.email,
|
email: req.user.email,
|
||||||
name: organizationName
|
name: organizationName
|
||||||
});
|
});
|
||||||
@@ -64,13 +52,6 @@ export const createOrganization = async (req: Request, res: Response) => {
|
|||||||
roles: [OWNER],
|
roles: [OWNER],
|
||||||
statuses: [ACCEPTED]
|
statuses: [ACCEPTED]
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to create organization'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
organization
|
organization
|
||||||
@@ -84,17 +65,7 @@ export const createOrganization = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getOrganization = async (req: Request, res: Response) => {
|
export const getOrganization = async (req: Request, res: Response) => {
|
||||||
let organization;
|
const organization = req.organization
|
||||||
try {
|
|
||||||
organization = req.organization
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to find organization'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
organization
|
organization
|
||||||
});
|
});
|
||||||
@@ -107,20 +78,11 @@ export const getOrganization = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getOrganizationMembers = async (req: Request, res: Response) => {
|
export const getOrganizationMembers = async (req: Request, res: Response) => {
|
||||||
let users;
|
|
||||||
try {
|
|
||||||
const { organizationId } = req.params;
|
const { organizationId } = req.params;
|
||||||
|
|
||||||
users = await MembershipOrg.find({
|
const users = await MembershipOrg.find({
|
||||||
organization: organizationId
|
organization: organizationId
|
||||||
}).populate('user', '+publicKey');
|
}).populate('user', '+publicKey');
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to get organization members'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
users
|
users
|
||||||
@@ -137,8 +99,6 @@ export const getOrganizationWorkspaces = async (
|
|||||||
req: Request,
|
req: Request,
|
||||||
res: Response
|
res: Response
|
||||||
) => {
|
) => {
|
||||||
let workspaces;
|
|
||||||
try {
|
|
||||||
const { organizationId } = req.params;
|
const { organizationId } = req.params;
|
||||||
|
|
||||||
const workspacesSet = new Set(
|
const workspacesSet = new Set(
|
||||||
@@ -152,20 +112,13 @@ export const getOrganizationWorkspaces = async (
|
|||||||
).map((w) => w._id.toString())
|
).map((w) => w._id.toString())
|
||||||
);
|
);
|
||||||
|
|
||||||
workspaces = (
|
const workspaces = (
|
||||||
await Membership.find({
|
await Membership.find({
|
||||||
user: req.user._id
|
user: req.user._id
|
||||||
}).populate('workspace')
|
}).populate('workspace')
|
||||||
)
|
)
|
||||||
.filter((m) => workspacesSet.has(m.workspace._id.toString()))
|
.filter((m) => workspacesSet.has(m.workspace._id.toString()))
|
||||||
.map((m) => m.workspace);
|
.map((m) => m.workspace);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to get my workspaces'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
workspaces
|
workspaces
|
||||||
@@ -179,12 +132,10 @@ export const getOrganizationWorkspaces = async (
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const changeOrganizationName = async (req: Request, res: Response) => {
|
export const changeOrganizationName = async (req: Request, res: Response) => {
|
||||||
let organization;
|
|
||||||
try {
|
|
||||||
const { organizationId } = req.params;
|
const { organizationId } = req.params;
|
||||||
const { name } = req.body;
|
const { name } = req.body;
|
||||||
|
|
||||||
organization = await Organization.findOneAndUpdate(
|
const organization = await Organization.findOneAndUpdate(
|
||||||
{
|
{
|
||||||
_id: organizationId
|
_id: organizationId
|
||||||
},
|
},
|
||||||
@@ -195,13 +146,6 @@ export const changeOrganizationName = async (req: Request, res: Response) => {
|
|||||||
new: true
|
new: true
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to change organization name'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Successfully changed organization name',
|
message: 'Successfully changed organization name',
|
||||||
@@ -219,20 +163,11 @@ export const getOrganizationIncidentContacts = async (
|
|||||||
req: Request,
|
req: Request,
|
||||||
res: Response
|
res: Response
|
||||||
) => {
|
) => {
|
||||||
let incidentContactsOrg;
|
|
||||||
try {
|
|
||||||
const { organizationId } = req.params;
|
const { organizationId } = req.params;
|
||||||
|
|
||||||
incidentContactsOrg = await IncidentContactOrg.find({
|
const incidentContactsOrg = await IncidentContactOrg.find({
|
||||||
organization: organizationId
|
organization: organizationId
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to get organization incident contacts'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
incidentContactsOrg
|
incidentContactsOrg
|
||||||
@@ -249,23 +184,14 @@ export const addOrganizationIncidentContact = async (
|
|||||||
req: Request,
|
req: Request,
|
||||||
res: Response
|
res: Response
|
||||||
) => {
|
) => {
|
||||||
let incidentContactOrg;
|
|
||||||
try {
|
|
||||||
const { organizationId } = req.params;
|
const { organizationId } = req.params;
|
||||||
const { email } = req.body;
|
const { email } = req.body;
|
||||||
|
|
||||||
incidentContactOrg = await IncidentContactOrg.findOneAndUpdate(
|
const incidentContactOrg = await IncidentContactOrg.findOneAndUpdate(
|
||||||
{ email, organization: organizationId },
|
{ email, organization: organizationId },
|
||||||
{ email, organization: organizationId },
|
{ email, organization: organizationId },
|
||||||
{ upsert: true, new: true }
|
{ upsert: true, new: true }
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to add incident contact for organization'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
incidentContactOrg
|
incidentContactOrg
|
||||||
@@ -282,22 +208,13 @@ export const deleteOrganizationIncidentContact = async (
|
|||||||
req: Request,
|
req: Request,
|
||||||
res: Response
|
res: Response
|
||||||
) => {
|
) => {
|
||||||
let incidentContactOrg;
|
|
||||||
try {
|
|
||||||
const { organizationId } = req.params;
|
const { organizationId } = req.params;
|
||||||
const { email } = req.body;
|
const { email } = req.body;
|
||||||
|
|
||||||
incidentContactOrg = await IncidentContactOrg.findOneAndDelete({
|
const incidentContactOrg = await IncidentContactOrg.findOneAndDelete({
|
||||||
email,
|
email,
|
||||||
organization: organizationId
|
organization: organizationId
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to delete organization incident contact'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Successfully deleted organization incident contact',
|
message: 'Successfully deleted organization incident contact',
|
||||||
@@ -317,7 +234,6 @@ export const createOrganizationPortalSession = async (
|
|||||||
res: Response
|
res: Response
|
||||||
) => {
|
) => {
|
||||||
let session;
|
let session;
|
||||||
try {
|
|
||||||
const stripe = new Stripe(await getStripeSecretKey(), {
|
const stripe = new Stripe(await getStripeSecretKey(), {
|
||||||
apiVersion: '2022-08-01'
|
apiVersion: '2022-08-01'
|
||||||
});
|
});
|
||||||
@@ -345,13 +261,6 @@ export const createOrganizationPortalSession = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
return res.status(200).send({ url: session.url });
|
return res.status(200).send({ url: session.url });
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to redirect to organization billing portal'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -364,22 +273,13 @@ export const getOrganizationSubscriptions = async (
|
|||||||
req: Request,
|
req: Request,
|
||||||
res: Response
|
res: Response
|
||||||
) => {
|
) => {
|
||||||
let subscriptions;
|
|
||||||
try {
|
|
||||||
const stripe = new Stripe(await getStripeSecretKey(), {
|
const stripe = new Stripe(await getStripeSecretKey(), {
|
||||||
apiVersion: '2022-08-01'
|
apiVersion: '2022-08-01'
|
||||||
});
|
});
|
||||||
|
|
||||||
subscriptions = await stripe.subscriptions.list({
|
const subscriptions = await stripe.subscriptions.list({
|
||||||
customer: req.organization.customerId
|
customer: req.organization.customerId
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to get organization subscriptions'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
subscriptions
|
subscriptions
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const jsrp = require('jsrp');
|
const jsrp = require('jsrp');
|
||||||
import * as bigintConversion from 'bigint-conversion';
|
import * as bigintConversion from 'bigint-conversion';
|
||||||
@@ -31,7 +30,6 @@ import {
|
|||||||
*/
|
*/
|
||||||
export const emailPasswordReset = async (req: Request, res: Response) => {
|
export const emailPasswordReset = async (req: Request, res: Response) => {
|
||||||
let email: string;
|
let email: string;
|
||||||
try {
|
|
||||||
email = req.body.email;
|
email = req.body.email;
|
||||||
|
|
||||||
const user = await User.findOne({ email }).select('+publicKey');
|
const user = await User.findOne({ email }).select('+publicKey');
|
||||||
@@ -58,13 +56,6 @@ export const emailPasswordReset = async (req: Request, res: Response) => {
|
|||||||
callback_url: (await getSiteURL()) + '/password-reset'
|
callback_url: (await getSiteURL()) + '/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({
|
return res.status(200).send({
|
||||||
message:"If an account exists with this email, a password reset link has been sent"
|
message:"If an account exists with this email, a password reset link has been sent"
|
||||||
@@ -78,11 +69,9 @@ export const emailPasswordReset = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const emailPasswordResetVerify = async (req: Request, res: Response) => {
|
export const emailPasswordResetVerify = async (req: Request, res: Response) => {
|
||||||
let user, token;
|
|
||||||
try {
|
|
||||||
const { email, code } = req.body;
|
const { email, code } = req.body;
|
||||||
|
|
||||||
user = await User.findOne({ email }).select('+publicKey');
|
const user = await User.findOne({ email }).select('+publicKey');
|
||||||
if (!user || !user?.publicKey) {
|
if (!user || !user?.publicKey) {
|
||||||
// case: user doesn't exist with email [email] or
|
// case: user doesn't exist with email [email] or
|
||||||
// hasn't even completed their account
|
// hasn't even completed their account
|
||||||
@@ -98,20 +87,13 @@ export const emailPasswordResetVerify = async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// generate temporary password-reset token
|
// generate temporary password-reset token
|
||||||
token = createToken({
|
const token = createToken({
|
||||||
payload: {
|
payload: {
|
||||||
userId: user._id.toString()
|
userId: user._id.toString()
|
||||||
},
|
},
|
||||||
expiresIn: await getJwtSignupLifetime(),
|
expiresIn: await getJwtSignupLifetime(),
|
||||||
secret: await getJwtSignupSecret()
|
secret: await getJwtSignupSecret()
|
||||||
});
|
});
|
||||||
} 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({
|
return res.status(200).send({
|
||||||
message: 'Successfully verified email',
|
message: 'Successfully verified email',
|
||||||
@@ -129,7 +111,6 @@ export const emailPasswordResetVerify = async (req: Request, res: Response) => {
|
|||||||
export const srp1 = async (req: Request, res: Response) => {
|
export const srp1 = async (req: Request, res: Response) => {
|
||||||
// return salt, serverPublicKey as part of first step of SRP protocol
|
// return salt, serverPublicKey as part of first step of SRP protocol
|
||||||
|
|
||||||
try {
|
|
||||||
const { clientPublicKey } = req.body;
|
const { clientPublicKey } = req.body;
|
||||||
const user = await User.findOne({
|
const user = await User.findOne({
|
||||||
email: req.user.email
|
email: req.user.email
|
||||||
@@ -159,14 +140,8 @@ export const srp1 = async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
}
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
error: 'Failed to start change password process'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change account SRP authentication information for user
|
* Change account SRP authentication information for user
|
||||||
@@ -177,7 +152,6 @@ export const srp1 = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const changePassword = async (req: Request, res: Response) => {
|
export const changePassword = async (req: Request, res: Response) => {
|
||||||
try {
|
|
||||||
const {
|
const {
|
||||||
clientProof,
|
clientProof,
|
||||||
protectedKey,
|
protectedKey,
|
||||||
@@ -257,13 +231,6 @@ export const changePassword = async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
error: 'Failed to change password. Try again?'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -277,7 +244,6 @@ export const createBackupPrivateKey = async (req: Request, res: Response) => {
|
|||||||
// requires verifying [clientProof] as part of second step of SRP protocol
|
// requires verifying [clientProof] as part of second step of SRP protocol
|
||||||
// as initiated in /srp1
|
// as initiated in /srp1
|
||||||
|
|
||||||
try {
|
|
||||||
const { clientProof, encryptedPrivateKey, iv, tag, salt, verifier } =
|
const { clientProof, encryptedPrivateKey, iv, tag, salt, verifier } =
|
||||||
req.body;
|
req.body;
|
||||||
const user = await User.findOne({
|
const user = await User.findOne({
|
||||||
@@ -333,13 +299,6 @@ export const createBackupPrivateKey = async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to update backup private key'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -349,20 +308,11 @@ export const createBackupPrivateKey = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getBackupPrivateKey = async (req: Request, res: Response) => {
|
export const getBackupPrivateKey = async (req: Request, res: Response) => {
|
||||||
let backupPrivateKey;
|
const backupPrivateKey = await BackupPrivateKey.findOne({
|
||||||
try {
|
|
||||||
backupPrivateKey = await BackupPrivateKey.findOne({
|
|
||||||
user: req.user._id
|
user: req.user._id
|
||||||
}).select('+encryptedPrivateKey +iv +tag');
|
}).select('+encryptedPrivateKey +iv +tag');
|
||||||
|
|
||||||
if (!backupPrivateKey) throw new Error('Failed to find backup private key');
|
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({
|
return res.status(200).send({
|
||||||
backupPrivateKey
|
backupPrivateKey
|
||||||
@@ -370,7 +320,6 @@ export const getBackupPrivateKey = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const resetPassword = async (req: Request, res: Response) => {
|
export const resetPassword = async (req: Request, res: Response) => {
|
||||||
try {
|
|
||||||
const {
|
const {
|
||||||
protectedKey,
|
protectedKey,
|
||||||
protectedKeyIV,
|
protectedKeyIV,
|
||||||
@@ -399,13 +348,6 @@ export const resetPassword = async (req: Request, res: Response) => {
|
|||||||
new: true
|
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({
|
return res.status(200).send({
|
||||||
message: 'Successfully reset password'
|
message: 'Successfully reset password'
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Types } from 'mongoose';
|
import { Types } from 'mongoose';
|
||||||
import { Key, Secret } from '../../models';
|
import { Key, Secret } from '../../models';
|
||||||
import {
|
import {
|
||||||
@@ -37,8 +36,6 @@ interface PushSecret {
|
|||||||
*/
|
*/
|
||||||
export const pushSecrets = async (req: Request, res: Response) => {
|
export const pushSecrets = async (req: Request, res: Response) => {
|
||||||
// upload (encrypted) secrets to workspace with id [workspaceId]
|
// upload (encrypted) secrets to workspace with id [workspaceId]
|
||||||
|
|
||||||
try {
|
|
||||||
const postHogClient = await TelemetryService.getPostHogClient();
|
const postHogClient = await TelemetryService.getPostHogClient();
|
||||||
let { secrets }: { secrets: PushSecret[] } = req.body;
|
let { secrets }: { secrets: PushSecret[] } = req.body;
|
||||||
const { keys, environment, channel } = req.body;
|
const { keys, environment, channel } = req.body;
|
||||||
@@ -90,14 +87,6 @@ export const pushSecrets = async (req: Request, res: Response) => {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to upload workspace secrets'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Successfully uploaded workspace secrets'
|
message: 'Successfully uploaded workspace secrets'
|
||||||
});
|
});
|
||||||
@@ -113,7 +102,7 @@ export const pushSecrets = async (req: Request, res: Response) => {
|
|||||||
export const pullSecrets = async (req: Request, res: Response) => {
|
export const pullSecrets = async (req: Request, res: Response) => {
|
||||||
let secrets;
|
let secrets;
|
||||||
let key;
|
let key;
|
||||||
try {
|
|
||||||
const postHogClient = await TelemetryService.getPostHogClient();
|
const postHogClient = await TelemetryService.getPostHogClient();
|
||||||
const environment: string = req.query.environment as string;
|
const environment: string = req.query.environment as string;
|
||||||
const channel: string = req.query.channel as string;
|
const channel: string = req.query.channel as string;
|
||||||
@@ -157,13 +146,6 @@ export const pullSecrets = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to pull workspace secrets'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
secrets,
|
secrets,
|
||||||
@@ -182,7 +164,7 @@ export const pullSecrets = async (req: Request, res: Response) => {
|
|||||||
export const pullSecretsServiceToken = async (req: Request, res: Response) => {
|
export const pullSecretsServiceToken = async (req: Request, res: Response) => {
|
||||||
let secrets;
|
let secrets;
|
||||||
let key;
|
let key;
|
||||||
try {
|
|
||||||
const postHogClient = await TelemetryService.getPostHogClient();
|
const postHogClient = await TelemetryService.getPostHogClient();
|
||||||
const environment: string = req.query.environment as string;
|
const environment: string = req.query.environment as string;
|
||||||
const channel: string = req.query.channel as string;
|
const channel: string = req.query.channel as string;
|
||||||
@@ -225,13 +207,6 @@ export const pullSecretsServiceToken = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.serviceToken.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to pull workspace secrets'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
secrets: reformatPullSecrets({ secrets }),
|
secrets: reformatPullSecrets({ secrets }),
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { User } from '../../models';
|
import { User } from '../../models';
|
||||||
import {
|
import {
|
||||||
sendEmailVerification,
|
sendEmailVerification,
|
||||||
@@ -19,7 +18,6 @@ import { validateUserEmail } from '../../validation';
|
|||||||
*/
|
*/
|
||||||
export const beginEmailSignup = async (req: Request, res: Response) => {
|
export const beginEmailSignup = async (req: Request, res: Response) => {
|
||||||
let email: string;
|
let email: string;
|
||||||
try {
|
|
||||||
email = req.body.email;
|
email = req.body.email;
|
||||||
|
|
||||||
// validate that email is not disposable
|
// validate that email is not disposable
|
||||||
@@ -36,13 +34,6 @@ export const beginEmailSignup = async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
// send send verification email
|
// send send verification email
|
||||||
await sendEmailVerification({ email });
|
await sendEmailVerification({ email });
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
error: 'Failed to send email verification code'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: `Sent an email verification code to ${email}`
|
message: `Sent an email verification code to ${email}`
|
||||||
@@ -58,7 +49,6 @@ export const beginEmailSignup = async (req: Request, res: Response) => {
|
|||||||
*/
|
*/
|
||||||
export const verifyEmailSignup = async (req: Request, res: Response) => {
|
export const verifyEmailSignup = async (req: Request, res: Response) => {
|
||||||
let user, token;
|
let user, token;
|
||||||
try {
|
|
||||||
const { email, code } = req.body;
|
const { email, code } = req.body;
|
||||||
|
|
||||||
// initialize user account
|
// initialize user account
|
||||||
@@ -100,13 +90,6 @@ export const verifyEmailSignup = async (req: Request, res: Response) => {
|
|||||||
expiresIn: await getJwtSignupLifetime(),
|
expiresIn: await getJwtSignupLifetime(),
|
||||||
secret: await getJwtSignupSecret()
|
secret: await getJwtSignupSecret()
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
error: 'Failed email verification'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Successfuly verified email',
|
message: 'Successfuly verified email',
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import Stripe from 'stripe';
|
import Stripe from 'stripe';
|
||||||
import { getStripeSecretKey, getStripeWebhookSecret } from '../../config';
|
import { getStripeSecretKey, getStripeWebhookSecret } from '../../config';
|
||||||
|
|
||||||
@@ -10,26 +9,17 @@ import { getStripeSecretKey, getStripeWebhookSecret } from '../../config';
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const handleWebhook = async (req: Request, res: Response) => {
|
export const handleWebhook = async (req: Request, res: Response) => {
|
||||||
let event;
|
|
||||||
try {
|
|
||||||
// check request for valid stripe signature
|
// check request for valid stripe signature
|
||||||
const stripe = new Stripe(await getStripeSecretKey(), {
|
const stripe = new Stripe(await getStripeSecretKey(), {
|
||||||
apiVersion: '2022-08-01'
|
apiVersion: '2022-08-01'
|
||||||
});
|
});
|
||||||
|
|
||||||
const sig = req.headers['stripe-signature'] as string;
|
const sig = req.headers['stripe-signature'] as string;
|
||||||
event = stripe.webhooks.constructEvent(
|
const event = stripe.webhooks.constructEvent(
|
||||||
req.body,
|
req.body,
|
||||||
sig,
|
sig,
|
||||||
await getStripeWebhookSecret()
|
await getStripeWebhookSecret()
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
error: 'Failed to process webhook'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case '':
|
case '':
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { UserAction } from '../../models';
|
import { UserAction } from '../../models';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,11 +10,9 @@ import { UserAction } from '../../models';
|
|||||||
export const addUserAction = async (req: Request, res: Response) => {
|
export const addUserAction = async (req: Request, res: Response) => {
|
||||||
// add/record new action [action] for user with id [req.user._id]
|
// add/record new action [action] for user with id [req.user._id]
|
||||||
|
|
||||||
let userAction;
|
|
||||||
try {
|
|
||||||
const { action } = req.body;
|
const { action } = req.body;
|
||||||
|
|
||||||
userAction = await UserAction.findOneAndUpdate(
|
const userAction = await UserAction.findOneAndUpdate(
|
||||||
{
|
{
|
||||||
user: req.user._id,
|
user: req.user._id,
|
||||||
action
|
action
|
||||||
@@ -26,13 +23,6 @@ export const addUserAction = async (req: Request, res: Response) => {
|
|||||||
upsert: true
|
upsert: true
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to record user action'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Successfully recorded user action',
|
message: 'Successfully recorded user action',
|
||||||
@@ -48,21 +38,12 @@ export const addUserAction = async (req: Request, res: Response) => {
|
|||||||
*/
|
*/
|
||||||
export const getUserAction = async (req: Request, res: Response) => {
|
export const getUserAction = async (req: Request, res: Response) => {
|
||||||
// get user action [action] for user with id [req.user._id]
|
// get user action [action] for user with id [req.user._id]
|
||||||
let userAction;
|
|
||||||
try {
|
|
||||||
const action: string = req.query.action as string;
|
const action: string = req.query.action as string;
|
||||||
|
|
||||||
userAction = await UserAction.findOne({
|
const userAction = await UserAction.findOne({
|
||||||
user: req.user._id,
|
user: req.user._id,
|
||||||
action
|
action
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to get user action'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
userAction
|
userAction
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import * as Sentry from "@sentry/node";
|
|
||||||
import {
|
import {
|
||||||
Workspace,
|
Workspace,
|
||||||
Membership,
|
Membership,
|
||||||
@@ -25,11 +24,9 @@ import { ADMIN } from "../../variables";
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getWorkspacePublicKeys = async (req: Request, res: Response) => {
|
export const getWorkspacePublicKeys = async (req: Request, res: Response) => {
|
||||||
let publicKeys;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
|
|
||||||
publicKeys = (
|
const publicKeys = (
|
||||||
await Membership.find({
|
await Membership.find({
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
}).populate<{ user: IUser }>("user", "publicKey")
|
}).populate<{ user: IUser }>("user", "publicKey")
|
||||||
@@ -39,13 +36,6 @@ export const getWorkspacePublicKeys = async (req: Request, res: Response) => {
|
|||||||
userId: member.user._id,
|
userId: member.user._id,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to get workspace member public keys",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
publicKeys,
|
publicKeys,
|
||||||
@@ -59,20 +49,11 @@ export const getWorkspacePublicKeys = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getWorkspaceMemberships = async (req: Request, res: Response) => {
|
export const getWorkspaceMemberships = async (req: Request, res: Response) => {
|
||||||
let users;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
|
|
||||||
users = await Membership.find({
|
const users = await Membership.find({
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
}).populate("user", "+publicKey");
|
}).populate("user", "+publicKey");
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to get workspace members",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
users,
|
users,
|
||||||
@@ -86,20 +67,11 @@ export const getWorkspaceMemberships = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getWorkspaces = async (req: Request, res: Response) => {
|
export const getWorkspaces = async (req: Request, res: Response) => {
|
||||||
let workspaces;
|
const workspaces = (
|
||||||
try {
|
|
||||||
workspaces = (
|
|
||||||
await Membership.find({
|
await Membership.find({
|
||||||
user: req.user._id,
|
user: req.user._id,
|
||||||
}).populate("workspace")
|
}).populate("workspace")
|
||||||
).map((m) => m.workspace);
|
).map((m) => m.workspace);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to get workspaces",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
workspaces,
|
workspaces,
|
||||||
@@ -113,20 +85,11 @@ export const getWorkspaces = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getWorkspace = async (req: Request, res: Response) => {
|
export const getWorkspace = async (req: Request, res: Response) => {
|
||||||
let workspace;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
|
|
||||||
workspace = await Workspace.findOne({
|
const workspace = await Workspace.findOne({
|
||||||
_id: workspaceId,
|
_id: workspaceId,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to get workspace",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
workspace,
|
workspace,
|
||||||
@@ -141,9 +104,6 @@ export const getWorkspace = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const createWorkspace = async (req: Request, res: Response) => {
|
export const createWorkspace = async (req: Request, res: Response) => {
|
||||||
let workspace;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { workspaceName, organizationId } = req.body;
|
const { workspaceName, organizationId } = req.body;
|
||||||
|
|
||||||
// validate organization membership
|
// validate organization membership
|
||||||
@@ -173,7 +133,7 @@ export const createWorkspace = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create workspace and add user as member
|
// create workspace and add user as member
|
||||||
workspace = await create({
|
const workspace = await create({
|
||||||
name: workspaceName,
|
name: workspaceName,
|
||||||
organizationId,
|
organizationId,
|
||||||
});
|
});
|
||||||
@@ -183,13 +143,6 @@ export const createWorkspace = async (req: Request, res: Response) => {
|
|||||||
workspaceId: workspace._id.toString(),
|
workspaceId: workspace._id.toString(),
|
||||||
roles: [ADMIN],
|
roles: [ADMIN],
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to create workspace",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
workspace,
|
workspace,
|
||||||
@@ -203,20 +156,12 @@ export const createWorkspace = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const deleteWorkspace = async (req: Request, res: Response) => {
|
export const deleteWorkspace = async (req: Request, res: Response) => {
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
|
|
||||||
// delete workspace
|
// delete workspace
|
||||||
await deleteWork({
|
await deleteWork({
|
||||||
id: workspaceId,
|
id: workspaceId,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to delete workspace",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: "Successfully deleted workspace",
|
message: "Successfully deleted workspace",
|
||||||
@@ -230,12 +175,10 @@ export const deleteWorkspace = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const changeWorkspaceName = async (req: Request, res: Response) => {
|
export const changeWorkspaceName = async (req: Request, res: Response) => {
|
||||||
let workspace;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
const { name } = req.body;
|
const { name } = req.body;
|
||||||
|
|
||||||
workspace = await Workspace.findOneAndUpdate(
|
const workspace = await Workspace.findOneAndUpdate(
|
||||||
{
|
{
|
||||||
_id: workspaceId,
|
_id: workspaceId,
|
||||||
},
|
},
|
||||||
@@ -246,13 +189,6 @@ export const changeWorkspaceName = async (req: Request, res: Response) => {
|
|||||||
new: true,
|
new: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to change workspace name",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: "Successfully changed workspace name",
|
message: "Successfully changed workspace name",
|
||||||
@@ -267,20 +203,11 @@ export const changeWorkspaceName = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getWorkspaceIntegrations = async (req: Request, res: Response) => {
|
export const getWorkspaceIntegrations = async (req: Request, res: Response) => {
|
||||||
let integrations;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
|
|
||||||
integrations = await Integration.find({
|
const integrations = await Integration.find({
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to get workspace integrations",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
integrations,
|
integrations,
|
||||||
@@ -297,20 +224,11 @@ export const getWorkspaceIntegrationAuthorizations = async (
|
|||||||
req: Request,
|
req: Request,
|
||||||
res: Response
|
res: Response
|
||||||
) => {
|
) => {
|
||||||
let authorizations;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
|
|
||||||
authorizations = await IntegrationAuth.find({
|
const authorizations = await IntegrationAuth.find({
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to get workspace integration authorizations",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
authorizations,
|
authorizations,
|
||||||
@@ -327,21 +245,12 @@ export const getWorkspaceServiceTokens = async (
|
|||||||
req: Request,
|
req: Request,
|
||||||
res: Response
|
res: Response
|
||||||
) => {
|
) => {
|
||||||
let serviceTokens;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
// ?? FIX.
|
// ?? FIX.
|
||||||
serviceTokens = await ServiceToken.find({
|
const serviceTokens = await ServiceToken.find({
|
||||||
user: req.user._id,
|
user: req.user._id,
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to get workspace service tokens",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
serviceTokens,
|
serviceTokens,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import bcrypt from 'bcrypt';
|
import bcrypt from 'bcrypt';
|
||||||
@@ -14,18 +13,9 @@ import { getSaltRounds } from '../../config';
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getAPIKeyData = async (req: Request, res: Response) => {
|
export const getAPIKeyData = async (req: Request, res: Response) => {
|
||||||
let apiKeyData;
|
const apiKeyData = await APIKeyData.find({
|
||||||
try {
|
|
||||||
apiKeyData = await APIKeyData.find({
|
|
||||||
user: req.user._id
|
user: req.user._id
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to get API key data'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
apiKeyData
|
apiKeyData
|
||||||
@@ -38,8 +28,6 @@ export const getAPIKeyData = async (req: Request, res: Response) => {
|
|||||||
* @param res
|
* @param res
|
||||||
*/
|
*/
|
||||||
export const createAPIKeyData = async (req: Request, res: Response) => {
|
export const createAPIKeyData = async (req: Request, res: Response) => {
|
||||||
let apiKey, apiKeyData;
|
|
||||||
try {
|
|
||||||
const { name, expiresIn } = req.body;
|
const { name, expiresIn } = req.body;
|
||||||
|
|
||||||
const secret = crypto.randomBytes(16).toString('hex');
|
const secret = crypto.randomBytes(16).toString('hex');
|
||||||
@@ -48,7 +36,7 @@ export const createAPIKeyData = async (req: Request, res: Response) => {
|
|||||||
const expiresAt = new Date();
|
const expiresAt = new Date();
|
||||||
expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn);
|
expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn);
|
||||||
|
|
||||||
apiKeyData = await new APIKeyData({
|
let apiKeyData = await new APIKeyData({
|
||||||
name,
|
name,
|
||||||
lastUsed: new Date(),
|
lastUsed: new Date(),
|
||||||
expiresAt,
|
expiresAt,
|
||||||
@@ -57,19 +45,12 @@ export const createAPIKeyData = async (req: Request, res: Response) => {
|
|||||||
}).save();
|
}).save();
|
||||||
|
|
||||||
// return api key data without sensitive data
|
// return api key data without sensitive data
|
||||||
apiKeyData = await APIKeyData.findById(apiKeyData._id);
|
// FIX: fix this any
|
||||||
|
apiKeyData = await APIKeyData.findById(apiKeyData._id) as any
|
||||||
|
|
||||||
if (!apiKeyData) throw new Error('Failed to find API key data');
|
if (!apiKeyData) throw new Error('Failed to find API key data');
|
||||||
|
|
||||||
apiKey = `ak.${apiKeyData._id.toString()}.${secret}`;
|
const apiKey = `ak.${apiKeyData._id.toString()}.${secret}`;
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to API key data'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
apiKey,
|
apiKey,
|
||||||
@@ -84,19 +65,8 @@ export const createAPIKeyData = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const deleteAPIKeyData = async (req: Request, res: Response) => {
|
export const deleteAPIKeyData = async (req: Request, res: Response) => {
|
||||||
let apiKeyData;
|
|
||||||
try {
|
|
||||||
const { apiKeyDataId } = req.params;
|
const { apiKeyDataId } = req.params;
|
||||||
|
const apiKeyData = await APIKeyData.findByIdAndDelete(apiKeyDataId);
|
||||||
apiKeyData = await APIKeyData.findByIdAndDelete(apiKeyDataId);
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to delete API key data'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
apiKeyData
|
apiKeyData
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
/* 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 bigintConversion from 'bigint-conversion';
|
import * as bigintConversion from 'bigint-conversion';
|
||||||
const jsrp = require('jsrp');
|
const jsrp = require('jsrp');
|
||||||
import { User, LoginSRPDetail } from '../../models';
|
import { User, LoginSRPDetail } from '../../models';
|
||||||
@@ -35,7 +34,6 @@ declare module 'jsonwebtoken' {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const login1 = async (req: Request, res: Response) => {
|
export const login1 = async (req: Request, res: Response) => {
|
||||||
try {
|
|
||||||
const {
|
const {
|
||||||
email,
|
email,
|
||||||
clientPublicKey
|
clientPublicKey
|
||||||
@@ -69,13 +67,7 @@ export const login1 = async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to start authentication process'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -86,14 +78,21 @@ 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 {
|
if (!req.headers['user-agent']) throw InternalServerError({ message: 'User-Agent header is required' });
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
if (!req.headers['user-agent']) throw InternalServerError({ message: 'User-Agent header is required' });
|
if (!req.headers['user-agent']) throw InternalServerError({ message: 'User-Agent header is required' });
|
||||||
|
|
||||||
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 +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag +devices');
|
}).select('+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag +devices');
|
||||||
|
=======
|
||||||
|
const { email, clientProof } = req.body;
|
||||||
|
const user = await User.findOne({
|
||||||
|
email
|
||||||
|
}).select('+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag');
|
||||||
|
>>>>>>> origin/main
|
||||||
|
|
||||||
if (!user) throw new Error('Failed to find user');
|
if (!user) throw new Error('Failed to find user');
|
||||||
|
|
||||||
@@ -103,6 +102,7 @@ export const login2 = async (req: Request, res: Response) => {
|
|||||||
return BadRequestError(Error("Failed to find login details for SRP"))
|
return BadRequestError(Error("Failed to find login details for SRP"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
const server = new jsrp.server();
|
const server = new jsrp.server();
|
||||||
server.init(
|
server.init(
|
||||||
{
|
{
|
||||||
@@ -162,6 +162,77 @@ export const login2 = async (req: Request, res: Response) => {
|
|||||||
userAgent: req.headers['user-agent'] ?? ''
|
userAgent: req.headers['user-agent'] ?? ''
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// store (refresh) token in httpOnly cookie
|
||||||
|
res.cookie('jid', tokens.refreshToken, {
|
||||||
|
httpOnly: true,
|
||||||
|
path: '/',
|
||||||
|
sameSite: 'strict',
|
||||||
|
secure: await getHttpsEnabled()
|
||||||
|
=======
|
||||||
|
const server = new jsrp.server();
|
||||||
|
server.init(
|
||||||
|
{
|
||||||
|
salt: user.salt,
|
||||||
|
verifier: user.verifier,
|
||||||
|
b: loginSRPDetail.serverBInt
|
||||||
|
},
|
||||||
|
async () => {
|
||||||
|
server.setClientPublicKey(loginSRPDetail.clientPublicKey);
|
||||||
|
|
||||||
|
// compare server and client shared keys
|
||||||
|
if (server.checkClientProof(clientProof)) {
|
||||||
|
|
||||||
|
if (user.isMfaEnabled) {
|
||||||
|
// case: user has MFA enabled
|
||||||
|
|
||||||
|
// generate temporary MFA token
|
||||||
|
const token = createToken({
|
||||||
|
payload: {
|
||||||
|
userId: user._id.toString()
|
||||||
|
},
|
||||||
|
expiresIn: await getJwtMfaLifetime(),
|
||||||
|
secret: await getJwtMfaSecret()
|
||||||
|
});
|
||||||
|
|
||||||
|
const code = await TokenService.createToken({
|
||||||
|
type: TOKEN_EMAIL_MFA,
|
||||||
|
email
|
||||||
|
>>>>>>> origin/main
|
||||||
|
});
|
||||||
|
|
||||||
|
// send MFA code [code] to [email]
|
||||||
|
await sendMail({
|
||||||
|
template: 'emailMfa.handlebars',
|
||||||
|
subjectLine: 'Infisical MFA code',
|
||||||
|
recipients: [email],
|
||||||
|
substitutions: {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
loginAction && await EELogService.createLog({
|
||||||
|
userId: user._id,
|
||||||
|
actions: [loginAction],
|
||||||
|
channel: getChannelFromUserAgent(req.headers['user-agent']),
|
||||||
|
ipAddress: req.realIP
|
||||||
|
=======
|
||||||
|
return res.status(200).send({
|
||||||
|
mfaEnabled: true,
|
||||||
|
token
|
||||||
|
>>>>>>> origin/main
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await checkUserDevice({
|
||||||
|
user,
|
||||||
|
ip: req.ip,
|
||||||
|
userAgent: req.headers['user-agent'] ?? ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// issue tokens
|
||||||
|
const tokens = await issueAuthTokens({ 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,
|
||||||
@@ -215,7 +286,7 @@ export const login2 = async (req: Request, res: Response) => {
|
|||||||
userId: user._id,
|
userId: user._id,
|
||||||
actions: [loginAction],
|
actions: [loginAction],
|
||||||
channel: getChannelFromUserAgent(req.headers['user-agent']),
|
channel: getChannelFromUserAgent(req.headers['user-agent']),
|
||||||
ipAddress: req.realIP
|
ipAddress: req.ip
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.status(200).send(response);
|
return res.status(200).send(response);
|
||||||
@@ -226,13 +297,6 @@ export const login2 = async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to authenticate. Try again?'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -241,7 +305,6 @@ export const login2 = async (req: Request, res: Response) => {
|
|||||||
* @param res
|
* @param res
|
||||||
*/
|
*/
|
||||||
export const sendMfaToken = async (req: Request, res: Response) => {
|
export const sendMfaToken = async (req: Request, res: Response) => {
|
||||||
try {
|
|
||||||
const { email } = req.body;
|
const { email } = req.body;
|
||||||
|
|
||||||
const code = await TokenService.createToken({
|
const code = await TokenService.createToken({
|
||||||
@@ -258,13 +321,6 @@ export const sendMfaToken = async (req: Request, res: Response) => {
|
|||||||
code
|
code
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to send MFA code'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Successfully sent new MFA code'
|
message: 'Successfully sent new MFA code'
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import {
|
import {
|
||||||
Secret,
|
Secret,
|
||||||
ServiceToken,
|
ServiceToken,
|
||||||
@@ -25,7 +24,6 @@ export const createWorkspaceEnvironment = async (
|
|||||||
) => {
|
) => {
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
const { environmentName, environmentSlug } = req.body;
|
const { environmentName, environmentSlug } = req.body;
|
||||||
try {
|
|
||||||
const workspace = await Workspace.findById(workspaceId).exec();
|
const workspace = await Workspace.findById(workspaceId).exec();
|
||||||
if (
|
if (
|
||||||
!workspace ||
|
!workspace ||
|
||||||
@@ -41,13 +39,6 @@ export const createWorkspaceEnvironment = async (
|
|||||||
slug: environmentSlug.toLowerCase(),
|
slug: environmentSlug.toLowerCase(),
|
||||||
});
|
});
|
||||||
await workspace.save();
|
await workspace.save();
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to create new workspace environment',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Successfully created new environment',
|
message: 'Successfully created new environment',
|
||||||
@@ -72,7 +63,6 @@ export const renameWorkspaceEnvironment = async (
|
|||||||
) => {
|
) => {
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
const { environmentName, environmentSlug, oldEnvironmentSlug } = req.body;
|
const { environmentName, environmentSlug, oldEnvironmentSlug } = req.body;
|
||||||
try {
|
|
||||||
// user should pass both new slug and env name
|
// user should pass both new slug and env name
|
||||||
if (!environmentSlug || !environmentName) {
|
if (!environmentSlug || !environmentName) {
|
||||||
throw new Error('Invalid environment given.');
|
throw new Error('Invalid environment given.');
|
||||||
@@ -133,13 +123,6 @@ export const renameWorkspaceEnvironment = async (
|
|||||||
{ arrayFilters: [{ "element.environmentSlug": oldEnvironmentSlug }] }
|
{ arrayFilters: [{ "element.environmentSlug": oldEnvironmentSlug }] }
|
||||||
)
|
)
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to update workspace environment',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Successfully update environment',
|
message: 'Successfully update environment',
|
||||||
@@ -163,7 +146,6 @@ export const deleteWorkspaceEnvironment = async (
|
|||||||
) => {
|
) => {
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
const { environmentSlug } = req.body;
|
const { environmentSlug } = req.body;
|
||||||
try {
|
|
||||||
// atomic update the env to avoid conflict
|
// atomic update the env to avoid conflict
|
||||||
const workspace = await Workspace.findById(workspaceId).exec();
|
const workspace = await Workspace.findById(workspaceId).exec();
|
||||||
if (!workspace) {
|
if (!workspace) {
|
||||||
@@ -206,14 +188,6 @@ export const deleteWorkspaceEnvironment = async (
|
|||||||
{ $pull: { deniedPermissions: { environmentSlug: environmentSlug } } }
|
{ $pull: { deniedPermissions: { environmentSlug: environmentSlug } } }
|
||||||
)
|
)
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to delete workspace environment',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Successfully deleted environment',
|
message: 'Successfully deleted environment',
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Types } from 'mongoose';
|
import { Types } from 'mongoose';
|
||||||
import {
|
import {
|
||||||
MembershipOrg,
|
MembershipOrg,
|
||||||
@@ -49,20 +48,11 @@ export const getOrganizationMemberships = async (req: Request, res: Response) =>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
let memberships;
|
|
||||||
try {
|
|
||||||
const { organizationId } = req.params;
|
const { organizationId } = req.params;
|
||||||
|
|
||||||
memberships = await MembershipOrg.find({
|
const memberships = await MembershipOrg.find({
|
||||||
organization: organizationId
|
organization: organizationId
|
||||||
}).populate('user', '+publicKey');
|
}).populate('user', '+publicKey');
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to get organization memberships'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
memberships
|
memberships
|
||||||
@@ -128,12 +118,10 @@ export const updateOrganizationMembership = async (req: Request, res: Response)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
let membership;
|
|
||||||
try {
|
|
||||||
const { membershipId } = req.params;
|
const { membershipId } = req.params;
|
||||||
const { role } = req.body;
|
const { role } = req.body;
|
||||||
|
|
||||||
membership = await MembershipOrg.findByIdAndUpdate(
|
const membership = await MembershipOrg.findByIdAndUpdate(
|
||||||
membershipId,
|
membershipId,
|
||||||
{
|
{
|
||||||
role
|
role
|
||||||
@@ -141,13 +129,6 @@ export const updateOrganizationMembership = async (req: Request, res: Response)
|
|||||||
new: true
|
new: true
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to update organization membership'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
membership
|
membership
|
||||||
@@ -197,25 +178,16 @@ export const deleteOrganizationMembership = async (req: Request, res: Response)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
let membership;
|
|
||||||
try {
|
|
||||||
const { membershipId } = req.params;
|
const { membershipId } = req.params;
|
||||||
|
|
||||||
// delete organization membership
|
// delete organization membership
|
||||||
membership = await deleteMembershipOrg({
|
const membership = await deleteMembershipOrg({
|
||||||
membershipOrgId: membershipId
|
membershipOrgId: membershipId
|
||||||
});
|
});
|
||||||
|
|
||||||
await updateSubscriptionOrgQuantity({
|
await updateSubscriptionOrgQuantity({
|
||||||
organizationId: membership.organization.toString()
|
organizationId: membership.organization.toString()
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to delete organization membership'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
membership
|
membership
|
||||||
|
|||||||
@@ -218,6 +218,7 @@ export const batchSecrets = async (req: Request, res: Response) => {
|
|||||||
algorithm: ALGORITHM_AES_256_GCM,
|
algorithm: ALGORITHM_AES_256_GCM,
|
||||||
keyEncoding: ENCODING_SCHEME_UTF8,
|
keyEncoding: ENCODING_SCHEME_UTF8,
|
||||||
tags: u.tags,
|
tags: u.tags,
|
||||||
|
folder: u.folder
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import bcrypt from 'bcrypt';
|
import bcrypt from 'bcrypt';
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { User, MembershipOrg } from '../../models';
|
import { User, MembershipOrg } from '../../models';
|
||||||
import { completeAccount } from '../../helpers/user';
|
import { completeAccount } from '../../helpers/user';
|
||||||
import {
|
import {
|
||||||
@@ -20,7 +19,6 @@ import { updateSubscriptionOrgQuantity } from '../../helpers/organization';
|
|||||||
*/
|
*/
|
||||||
export const completeAccountSignup = async (req: Request, res: Response) => {
|
export const completeAccountSignup = async (req: Request, res: Response) => {
|
||||||
let user, token, refreshToken;
|
let user, token, refreshToken;
|
||||||
try {
|
|
||||||
const {
|
const {
|
||||||
email,
|
email,
|
||||||
firstName,
|
firstName,
|
||||||
@@ -114,12 +112,19 @@ export const completeAccountSignup = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
// issue tokens
|
// issue tokens
|
||||||
const tokens = await issueAuthTokens({
|
const tokens = await issueAuthTokens({
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
ip: req.realIP,
|
ip: req.realIP,
|
||||||
userAgent: req.headers['user-agent'] ?? ''
|
userAgent: req.headers['user-agent'] ?? ''
|
||||||
});
|
});
|
||||||
|
=======
|
||||||
|
// issue tokens
|
||||||
|
const tokens = await issueAuthTokens({
|
||||||
|
userId: user._id.toString()
|
||||||
|
});
|
||||||
|
>>>>>>> origin/main
|
||||||
|
|
||||||
token = tokens.token;
|
token = tokens.token;
|
||||||
|
|
||||||
@@ -145,13 +150,6 @@ export const completeAccountSignup = async (req: Request, res: Response) => {
|
|||||||
sameSite: 'strict',
|
sameSite: 'strict',
|
||||||
secure: await getHttpsEnabled()
|
secure: await getHttpsEnabled()
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to complete account setup'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Successfully set up account',
|
message: 'Successfully set up account',
|
||||||
@@ -169,7 +167,6 @@ export const completeAccountSignup = async (req: Request, res: Response) => {
|
|||||||
*/
|
*/
|
||||||
export const completeAccountInvite = async (req: Request, res: Response) => {
|
export const completeAccountInvite = async (req: Request, res: Response) => {
|
||||||
let user, token, refreshToken;
|
let user, token, refreshToken;
|
||||||
try {
|
|
||||||
const {
|
const {
|
||||||
email,
|
email,
|
||||||
firstName,
|
firstName,
|
||||||
@@ -247,12 +244,19 @@ export const completeAccountInvite = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
// issue tokens
|
// issue tokens
|
||||||
const tokens = await issueAuthTokens({
|
const tokens = await issueAuthTokens({
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
ip: req.realIP,
|
ip: req.realIP,
|
||||||
userAgent: req.headers['user-agent'] ?? ''
|
userAgent: req.headers['user-agent'] ?? ''
|
||||||
});
|
});
|
||||||
|
=======
|
||||||
|
// issue tokens
|
||||||
|
const tokens = await issueAuthTokens({
|
||||||
|
userId: user._id.toString()
|
||||||
|
});
|
||||||
|
>>>>>>> origin/main
|
||||||
|
|
||||||
token = tokens.token;
|
token = tokens.token;
|
||||||
|
|
||||||
@@ -263,13 +267,6 @@ export const completeAccountInvite = async (req: Request, res: Response) => {
|
|||||||
sameSite: 'strict',
|
sameSite: 'strict',
|
||||||
secure: await getHttpsEnabled()
|
secure: await getHttpsEnabled()
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to complete account setup'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Successfully set up account',
|
message: 'Successfully set up account',
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Types } from 'mongoose';
|
import { Types } from 'mongoose';
|
||||||
import {
|
import {
|
||||||
Membership, Secret,
|
Membership, Secret,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import {
|
import {
|
||||||
User,
|
User,
|
||||||
MembershipOrg
|
MembershipOrg
|
||||||
@@ -37,18 +36,9 @@ export const getMe = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
let user;
|
const user = await User
|
||||||
try {
|
|
||||||
user = await User
|
|
||||||
.findById(req.user._id)
|
.findById(req.user._id)
|
||||||
.select('+salt +publicKey +encryptedPrivateKey +iv +tag +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag');
|
.select('+salt +publicKey +encryptedPrivateKey +iv +tag +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag');
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to get current user'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
user
|
user
|
||||||
@@ -64,8 +54,6 @@ export const getMe = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const updateMyMfaEnabled = async (req: Request, res: Response) => {
|
export const updateMyMfaEnabled = async (req: Request, res: Response) => {
|
||||||
let user;
|
|
||||||
try {
|
|
||||||
const { isMfaEnabled }: { isMfaEnabled: boolean } = req.body;
|
const { isMfaEnabled }: { isMfaEnabled: boolean } = req.body;
|
||||||
req.user.isMfaEnabled = isMfaEnabled;
|
req.user.isMfaEnabled = isMfaEnabled;
|
||||||
|
|
||||||
@@ -79,14 +67,7 @@ export const updateMyMfaEnabled = async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
await req.user.save();
|
await req.user.save();
|
||||||
|
|
||||||
user = req.user;
|
const user = req.user;
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to update current user's MFA status"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
user
|
user
|
||||||
@@ -126,20 +107,11 @@ export const getMyOrganizations = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
let organizations;
|
const organizations = (
|
||||||
try {
|
|
||||||
organizations = (
|
|
||||||
await MembershipOrg.find({
|
await MembershipOrg.find({
|
||||||
user: req.user._id
|
user: req.user._id
|
||||||
}).populate('organization')
|
}).populate('organization')
|
||||||
).map((m) => m.organization);
|
).map((m) => m.organization);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to get current user's organizations"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
organizations
|
organizations
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Types } from 'mongoose';
|
import { Types } from 'mongoose';
|
||||||
import {
|
import {
|
||||||
Workspace,
|
Workspace,
|
||||||
@@ -47,6 +46,7 @@ interface V2PushSecret {
|
|||||||
*/
|
*/
|
||||||
export const pushWorkspaceSecrets = async (req: Request, res: Response) => {
|
export const pushWorkspaceSecrets = async (req: Request, res: Response) => {
|
||||||
// upload (encrypted) secrets to workspace with id [workspaceId]
|
// upload (encrypted) secrets to workspace with id [workspaceId]
|
||||||
|
<<<<<<< HEAD
|
||||||
try {
|
try {
|
||||||
const postHogClient = await TelemetryService.getPostHogClient();
|
const postHogClient = await TelemetryService.getPostHogClient();
|
||||||
let { secrets }: { secrets: V2PushSecret[] } = req.body;
|
let { secrets }: { secrets: V2PushSecret[] } = req.body;
|
||||||
@@ -107,6 +107,59 @@ export const pushWorkspaceSecrets = async (req: Request, res: Response) => {
|
|||||||
message: 'Failed to upload workspace secrets'
|
message: 'Failed to upload workspace secrets'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
=======
|
||||||
|
const postHogClient = await TelemetryService.getPostHogClient();
|
||||||
|
let { secrets }: { secrets: V2PushSecret[] } = req.body;
|
||||||
|
const { keys, environment, channel } = req.body;
|
||||||
|
const { workspaceId } = req.params;
|
||||||
|
|
||||||
|
// validate environment
|
||||||
|
const workspaceEnvs = req.membership.workspace.environments;
|
||||||
|
if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) {
|
||||||
|
throw new Error('Failed to validate environment');
|
||||||
|
}
|
||||||
|
|
||||||
|
// sanitize secrets
|
||||||
|
secrets = secrets.filter(
|
||||||
|
(s: V2PushSecret) => s.secretKeyCiphertext !== '' && s.secretValueCiphertext !== ''
|
||||||
|
);
|
||||||
|
|
||||||
|
await push({
|
||||||
|
userId: req.user._id,
|
||||||
|
workspaceId,
|
||||||
|
environment,
|
||||||
|
secrets,
|
||||||
|
channel: channel ? channel : 'cli',
|
||||||
|
ipAddress: req.ip
|
||||||
|
});
|
||||||
|
|
||||||
|
await pushKeys({
|
||||||
|
userId: req.user._id,
|
||||||
|
workspaceId,
|
||||||
|
keys
|
||||||
|
});
|
||||||
|
|
||||||
|
if (postHogClient) {
|
||||||
|
postHogClient.capture({
|
||||||
|
event: 'secrets pushed',
|
||||||
|
distinctId: req.user.email,
|
||||||
|
properties: {
|
||||||
|
numberOfSecrets: secrets.length,
|
||||||
|
environment,
|
||||||
|
workspaceId,
|
||||||
|
channel: channel ? channel : 'cli'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// trigger event - push secrets
|
||||||
|
EventService.handleEvent({
|
||||||
|
event: eventPushSecrets({
|
||||||
|
workspaceId: new Types.ObjectId(workspaceId),
|
||||||
|
environment
|
||||||
|
})
|
||||||
|
});
|
||||||
|
>>>>>>> origin/main
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Successfully uploaded workspace secrets'
|
message: 'Successfully uploaded workspace secrets'
|
||||||
@@ -121,6 +174,7 @@ export const pushWorkspaceSecrets = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const pullSecrets = async (req: Request, res: Response) => {
|
export const pullSecrets = async (req: Request, res: Response) => {
|
||||||
|
<<<<<<< HEAD
|
||||||
let secrets;
|
let secrets;
|
||||||
try {
|
try {
|
||||||
const postHogClient = await TelemetryService.getPostHogClient();
|
const postHogClient = await TelemetryService.getPostHogClient();
|
||||||
@@ -172,6 +226,51 @@ export const pullSecrets = async (req: Request, res: Response) => {
|
|||||||
message: 'Failed to pull workspace secrets'
|
message: 'Failed to pull workspace secrets'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
=======
|
||||||
|
const postHogClient = await TelemetryService.getPostHogClient();
|
||||||
|
const environment: string = req.query.environment as string;
|
||||||
|
const channel: string = req.query.channel as string;
|
||||||
|
const { workspaceId } = req.params;
|
||||||
|
|
||||||
|
let userId;
|
||||||
|
if (req.user) {
|
||||||
|
userId = req.user._id.toString();
|
||||||
|
} else if (req.serviceTokenData) {
|
||||||
|
userId = req.serviceTokenData.user.toString();
|
||||||
|
}
|
||||||
|
// validate environment
|
||||||
|
const workspaceEnvs = req.membership.workspace.environments;
|
||||||
|
if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) {
|
||||||
|
throw new Error('Failed to validate environment');
|
||||||
|
}
|
||||||
|
|
||||||
|
let secrets = await pull({
|
||||||
|
userId,
|
||||||
|
workspaceId,
|
||||||
|
environment,
|
||||||
|
channel: channel ? channel : 'cli',
|
||||||
|
ipAddress: req.ip
|
||||||
|
});
|
||||||
|
|
||||||
|
if (channel !== 'cli') {
|
||||||
|
// FIX: Fix this any
|
||||||
|
secrets = reformatPullSecrets({ secrets }) as any;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (postHogClient) {
|
||||||
|
// capture secrets pushed event in production
|
||||||
|
postHogClient.capture({
|
||||||
|
distinctId: req.user.email,
|
||||||
|
event: 'secrets pulled',
|
||||||
|
properties: {
|
||||||
|
numberOfSecrets: secrets.length,
|
||||||
|
environment,
|
||||||
|
workspaceId,
|
||||||
|
channel: channel ? channel : 'cli'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
>>>>>>> origin/main
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
secrets
|
secrets
|
||||||
@@ -208,7 +307,6 @@ export const getWorkspaceKey = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
let key;
|
let key;
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
|
|
||||||
key = await Key.findOne({
|
key = await Key.findOne({
|
||||||
@@ -217,13 +315,6 @@ export const getWorkspaceKey = async (req: Request, res: Response) => {
|
|||||||
}).populate('sender', '+publicKey');
|
}).populate('sender', '+publicKey');
|
||||||
|
|
||||||
if (!key) throw new Error('Failed to find workspace key');
|
if (!key) throw new Error('Failed to find workspace key');
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to get workspace key'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).json(key);
|
return res.status(200).json(key);
|
||||||
}
|
}
|
||||||
@@ -231,24 +322,14 @@ export const getWorkspaceServiceTokenData = async (
|
|||||||
req: Request,
|
req: Request,
|
||||||
res: Response
|
res: Response
|
||||||
) => {
|
) => {
|
||||||
let serviceTokenData;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
|
|
||||||
serviceTokenData = await ServiceTokenData
|
const serviceTokenData = await ServiceTokenData
|
||||||
.find({
|
.find({
|
||||||
workspace: workspaceId
|
workspace: workspaceId
|
||||||
})
|
})
|
||||||
.select('+encryptedKey +iv +tag');
|
.select('+encryptedKey +iv +tag');
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to get workspace service token data'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
serviceTokenData
|
serviceTokenData
|
||||||
});
|
});
|
||||||
@@ -294,20 +375,11 @@ export const getWorkspaceMemberships = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
let memberships;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
|
|
||||||
memberships = await Membership.find({
|
const memberships = await Membership.find({
|
||||||
workspace: workspaceId
|
workspace: workspaceId
|
||||||
}).populate('user', '+publicKey');
|
}).populate('user', '+publicKey');
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to get workspace memberships'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
memberships
|
memberships
|
||||||
@@ -374,14 +446,12 @@ export const updateWorkspaceMembership = async (req: Request, res: Response) =>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
let membership;
|
|
||||||
try {
|
|
||||||
const {
|
const {
|
||||||
membershipId
|
membershipId
|
||||||
} = req.params;
|
} = req.params;
|
||||||
const { role } = req.body;
|
const { role } = req.body;
|
||||||
|
|
||||||
membership = await Membership.findByIdAndUpdate(
|
const membership = await Membership.findByIdAndUpdate(
|
||||||
membershipId,
|
membershipId,
|
||||||
{
|
{
|
||||||
role
|
role
|
||||||
@@ -389,13 +459,6 @@ export const updateWorkspaceMembership = async (req: Request, res: Response) =>
|
|||||||
new: true
|
new: true
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to update workspace membership'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
membership
|
membership
|
||||||
@@ -445,13 +508,11 @@ export const deleteWorkspaceMembership = async (req: Request, res: Response) =>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
let membership;
|
|
||||||
try {
|
|
||||||
const {
|
const {
|
||||||
membershipId
|
membershipId
|
||||||
} = req.params;
|
} = req.params;
|
||||||
|
|
||||||
membership = await Membership.findByIdAndDelete(membershipId);
|
const membership = await Membership.findByIdAndDelete(membershipId);
|
||||||
|
|
||||||
if (!membership) throw new Error('Failed to delete workspace membership');
|
if (!membership) throw new Error('Failed to delete workspace membership');
|
||||||
|
|
||||||
@@ -459,13 +520,6 @@ export const deleteWorkspaceMembership = async (req: Request, res: Response) =>
|
|||||||
receiver: membership.user,
|
receiver: membership.user,
|
||||||
workspace: membership.workspace
|
workspace: membership.workspace
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to delete workspace membership'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
membership
|
membership
|
||||||
@@ -479,12 +533,10 @@ export const deleteWorkspaceMembership = async (req: Request, res: Response) =>
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const toggleAutoCapitalization = async (req: Request, res: Response) => {
|
export const toggleAutoCapitalization = async (req: Request, res: Response) => {
|
||||||
let workspace;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
const { autoCapitalization } = req.body;
|
const { autoCapitalization } = req.body;
|
||||||
|
|
||||||
workspace = await Workspace.findOneAndUpdate(
|
const workspace = await Workspace.findOneAndUpdate(
|
||||||
{
|
{
|
||||||
_id: workspaceId
|
_id: workspaceId
|
||||||
},
|
},
|
||||||
@@ -495,13 +547,6 @@ export const toggleAutoCapitalization = async (req: Request, res: Response) => {
|
|||||||
new: true
|
new: true
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'Failed to change autoCapitalization setting'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: 'Successfully changed autoCapitalization setting',
|
message: 'Successfully changed autoCapitalization setting',
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Action, SecretVersion } from '../../models';
|
import { Action, SecretVersion } from '../../models';
|
||||||
import { ActionNotFoundError } from '../../../utils/errors';
|
import { ActionNotFoundError } from '../../../utils/errors';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { EELicenseService } from '../../services';
|
import { EELicenseService } from '../../services';
|
||||||
import { getLicenseServerUrl } from '../../../config';
|
import { getLicenseServerUrl } from '../../../config';
|
||||||
@@ -12,7 +11,6 @@ import { licenseServerKeyRequest } from '../../../config/request';
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getCloudProducts = async (req: Request, res: Response) => {
|
export const getCloudProducts = async (req: Request, res: Response) => {
|
||||||
try {
|
|
||||||
const billingCycle = req.query['billing-cycle'] as string;
|
const billingCycle = req.query['billing-cycle'] as string;
|
||||||
|
|
||||||
if (EELicenseService.instanceType === 'cloud') {
|
if (EELicenseService.instanceType === 'cloud') {
|
||||||
@@ -22,10 +20,6 @@ export const getCloudProducts = async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
return res.status(200).send(data);
|
return res.status(200).send(data);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
head: [],
|
head: [],
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import * as Sentry from "@sentry/node";
|
|
||||||
import { Secret } from "../../../models";
|
import { Secret } from "../../../models";
|
||||||
import { SecretVersion } from "../../models";
|
import { SecretVersion } from "../../models";
|
||||||
import { EESecretService } from "../../services";
|
import { EESecretService } from "../../services";
|
||||||
@@ -55,14 +54,12 @@ export const getSecretVersions = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
let secretVersions;
|
|
||||||
try {
|
|
||||||
const { secretId, workspaceId, environment, folderId } = req.params;
|
const { secretId, workspaceId, environment, folderId } = req.params;
|
||||||
|
|
||||||
const offset: number = parseInt(req.query.offset as string);
|
const offset: number = parseInt(req.query.offset as string);
|
||||||
const limit: number = parseInt(req.query.limit as string);
|
const limit: number = parseInt(req.query.limit as string);
|
||||||
|
|
||||||
secretVersions = await SecretVersion.find({
|
const secretVersions = await SecretVersion.find({
|
||||||
secret: secretId,
|
secret: secretId,
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
environment,
|
environment,
|
||||||
@@ -71,13 +68,6 @@ export const getSecretVersions = async (req: Request, res: Response) => {
|
|||||||
.sort({ createdAt: -1 })
|
.sort({ createdAt: -1 })
|
||||||
.skip(offset)
|
.skip(offset)
|
||||||
.limit(limit);
|
.limit(limit);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to get secret versions",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
secretVersions,
|
secretVersions,
|
||||||
@@ -139,8 +129,6 @@ export const rollbackSecretVersion = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
let secret;
|
|
||||||
try {
|
|
||||||
const { secretId } = req.params;
|
const { secretId } = req.params;
|
||||||
const { version } = req.body;
|
const { version } = req.body;
|
||||||
|
|
||||||
@@ -164,13 +152,13 @@ export const rollbackSecretVersion = async (req: Request, res: Response) => {
|
|||||||
secretValueCiphertext,
|
secretValueCiphertext,
|
||||||
secretValueIV,
|
secretValueIV,
|
||||||
secretValueTag,
|
secretValueTag,
|
||||||
folder,
|
|
||||||
algorithm,
|
algorithm,
|
||||||
|
folder,
|
||||||
keyEncoding,
|
keyEncoding,
|
||||||
} = oldSecretVersion;
|
} = oldSecretVersion;
|
||||||
|
|
||||||
// update secret
|
// update secret
|
||||||
secret = await Secret.findByIdAndUpdate(
|
const secret = await Secret.findByIdAndUpdate(
|
||||||
secretId,
|
secretId,
|
||||||
{
|
{
|
||||||
$inc: {
|
$inc: {
|
||||||
@@ -225,13 +213,6 @@ export const rollbackSecretVersion = async (req: Request, res: Response) => {
|
|||||||
environment,
|
environment,
|
||||||
folderId: folder,
|
folderId: folder,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to roll back secret version",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
secret,
|
secret,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import * as Sentry from "@sentry/node";
|
|
||||||
import {
|
import {
|
||||||
ISecretVersion,
|
ISecretVersion,
|
||||||
SecretSnapshot,
|
SecretSnapshot,
|
||||||
@@ -13,23 +12,21 @@ import {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getSecretSnapshot = async (req: Request, res: Response) => {
|
export const getSecretSnapshot = async (req: Request, res: Response) => {
|
||||||
let secretSnapshot;
|
|
||||||
try {
|
|
||||||
const { secretSnapshotId } = req.params;
|
const { secretSnapshotId } = req.params;
|
||||||
|
|
||||||
secretSnapshot = await SecretSnapshot.findById(secretSnapshotId)
|
const secretSnapshot = await SecretSnapshot.findById(secretSnapshotId)
|
||||||
.lean()
|
.lean()
|
||||||
.populate<{ secretVersions: ISecretVersion[] }>("secretVersions")
|
.populate<{ secretVersions: ISecretVersion[] }>({
|
||||||
|
path: 'secretVersions',
|
||||||
|
populate: {
|
||||||
|
path: 'tags',
|
||||||
|
model: 'Tag'
|
||||||
|
}
|
||||||
|
})
|
||||||
.populate<{ folderVersion: TFolderRootVersionSchema }>("folderVersion");
|
.populate<{ folderVersion: TFolderRootVersionSchema }>("folderVersion");
|
||||||
|
|
||||||
if (!secretSnapshot) throw new Error("Failed to find secret snapshot");
|
if (!secretSnapshot) throw new Error("Failed to find secret snapshot");
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to get secret snapshot",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const folderId = secretSnapshot.folderId;
|
const folderId = secretSnapshot.folderId;
|
||||||
// to show only the folder required secrets
|
// to show only the folder required secrets
|
||||||
secretSnapshot.secretVersions = secretSnapshot.secretVersions.filter(
|
secretSnapshot.secretVersions = secretSnapshot.secretVersions.filter(
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import Stripe from 'stripe';
|
import Stripe from 'stripe';
|
||||||
import { getStripeSecretKey, getStripeWebhookSecret } from '../../../config';
|
import { getStripeSecretKey, getStripeWebhookSecret } from '../../../config';
|
||||||
@@ -10,26 +9,17 @@ import { getStripeSecretKey, getStripeWebhookSecret } from '../../../config';
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const handleWebhook = async (req: Request, res: Response) => {
|
export const handleWebhook = async (req: Request, res: Response) => {
|
||||||
let event;
|
|
||||||
try {
|
|
||||||
const stripe = new Stripe(await getStripeSecretKey(), {
|
const stripe = new Stripe(await getStripeSecretKey(), {
|
||||||
apiVersion: '2022-08-01'
|
apiVersion: '2022-08-01'
|
||||||
});
|
});
|
||||||
|
|
||||||
// check request for valid stripe signature
|
// check request for valid stripe signature
|
||||||
const sig = req.headers['stripe-signature'] as string;
|
const sig = req.headers['stripe-signature'] as string;
|
||||||
event = stripe.webhooks.constructEvent(
|
const event = stripe.webhooks.constructEvent(
|
||||||
req.body,
|
req.body,
|
||||||
sig,
|
sig,
|
||||||
await getStripeWebhookSecret()
|
await getStripeWebhookSecret()
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
error: 'Failed to process webhook'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case '':
|
case '':
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import * as Sentry from "@sentry/node";
|
|
||||||
import { PipelineStage, Types } from "mongoose";
|
import { PipelineStage, Types } from "mongoose";
|
||||||
import { Secret } from "../../../models";
|
import { Secret } from "../../../models";
|
||||||
import {
|
import {
|
||||||
@@ -69,15 +68,13 @@ export const getWorkspaceSecretSnapshots = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
let secretSnapshots;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
const { environment, folderId } = req.query;
|
const { environment, folderId } = req.query;
|
||||||
|
|
||||||
const offset: number = parseInt(req.query.offset as string);
|
const offset: number = parseInt(req.query.offset as string);
|
||||||
const limit: number = parseInt(req.query.limit as string);
|
const limit: number = parseInt(req.query.limit as string);
|
||||||
|
|
||||||
secretSnapshots = await SecretSnapshot.find({
|
const secretSnapshots = await SecretSnapshot.find({
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
environment,
|
environment,
|
||||||
folderId: folderId || "root",
|
folderId: folderId || "root",
|
||||||
@@ -85,13 +82,6 @@ export const getWorkspaceSecretSnapshots = async (
|
|||||||
.sort({ createdAt: -1 })
|
.sort({ createdAt: -1 })
|
||||||
.skip(offset)
|
.skip(offset)
|
||||||
.limit(limit);
|
.limit(limit);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to get secret snapshots",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
secretSnapshots,
|
secretSnapshots,
|
||||||
@@ -107,23 +97,14 @@ export const getWorkspaceSecretSnapshotsCount = async (
|
|||||||
req: Request,
|
req: Request,
|
||||||
res: Response
|
res: Response
|
||||||
) => {
|
) => {
|
||||||
let count;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
const { environment, folderId } = req.query;
|
const { environment, folderId } = req.query;
|
||||||
|
|
||||||
count = await SecretSnapshot.countDocuments({
|
const count = await SecretSnapshot.countDocuments({
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
environment,
|
environment,
|
||||||
folderId: folderId || "root",
|
folderId: folderId || "root",
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to count number of secret snapshots",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
count,
|
count,
|
||||||
@@ -191,8 +172,6 @@ export const rollbackWorkspaceSecretSnapshot = async (
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let secrets;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
const { version, environment, folderId = "root" } = req.body;
|
const { version, environment, folderId = "root" } = req.body;
|
||||||
|
|
||||||
@@ -376,7 +355,7 @@ export const rollbackWorkspaceSecretSnapshot = async (
|
|||||||
});
|
});
|
||||||
|
|
||||||
// add secrets
|
// add secrets
|
||||||
secrets = await Secret.insertMany(
|
const secrets = await Secret.insertMany(
|
||||||
Object.keys(oldSecretVersionsObj).map((sv) => {
|
Object.keys(oldSecretVersionsObj).map((sv) => {
|
||||||
const {
|
const {
|
||||||
secret: secretId,
|
secret: secretId,
|
||||||
@@ -501,13 +480,6 @@ export const rollbackWorkspaceSecretSnapshot = async (
|
|||||||
environment,
|
environment,
|
||||||
folderId,
|
folderId,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to roll back secret snapshot",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
secrets,
|
secrets,
|
||||||
@@ -587,8 +559,6 @@ export const getWorkspaceLogs = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
let logs;
|
|
||||||
try {
|
|
||||||
const { workspaceId } = req.params;
|
const { workspaceId } = req.params;
|
||||||
|
|
||||||
const offset: number = parseInt(req.query.offset as string);
|
const offset: number = parseInt(req.query.offset as string);
|
||||||
@@ -597,7 +567,7 @@ export const getWorkspaceLogs = async (req: Request, res: Response) => {
|
|||||||
const userId: string = req.query.userId as string;
|
const userId: string = req.query.userId as string;
|
||||||
const actionNames: string = req.query.actionNames as string;
|
const actionNames: string = req.query.actionNames as string;
|
||||||
|
|
||||||
logs = await Log.find({
|
const logs = await Log.find({
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
...(userId ? { user: userId } : {}),
|
...(userId ? { user: userId } : {}),
|
||||||
...(actionNames
|
...(actionNames
|
||||||
@@ -613,13 +583,6 @@ export const getWorkspaceLogs = async (req: Request, res: Response) => {
|
|||||||
.limit(limit)
|
.limit(limit)
|
||||||
.populate("actions")
|
.populate("actions")
|
||||||
.populate("user serviceAccount serviceTokenData");
|
.populate("user serviceAccount serviceTokenData");
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser({ email: req.user.email });
|
|
||||||
Sentry.captureException(err);
|
|
||||||
return res.status(400).send({
|
|
||||||
message: "Failed to get workspace logs",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
logs,
|
logs,
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export interface ISecretVersion {
|
|||||||
keyEncoding: "utf8" | "base64";
|
keyEncoding: "utf8" | "base64";
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
folder?: string;
|
folder?: string;
|
||||||
|
tags?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const secretVersionSchema = new Schema<ISecretVersion>(
|
const secretVersionSchema = new Schema<ISecretVersion>(
|
||||||
@@ -112,6 +113,11 @@ const secretVersionSchema = new Schema<ISecretVersion>(
|
|||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
tags: {
|
||||||
|
ref: 'Tag',
|
||||||
|
type: [Schema.Types.ObjectId],
|
||||||
|
default: []
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
timestamps: true,
|
timestamps: true,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import NodeCache from 'node-cache';
|
import NodeCache from 'node-cache';
|
||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import {
|
import {
|
||||||
getLicenseKey,
|
getLicenseKey,
|
||||||
getLicenseServerKey,
|
getLicenseServerKey,
|
||||||
@@ -98,7 +97,6 @@ class EELicenseService {
|
|||||||
const licenseServerKey = await getLicenseServerKey();
|
const licenseServerKey = await getLicenseServerKey();
|
||||||
const licenseKey = await getLicenseKey();
|
const licenseKey = await getLicenseKey();
|
||||||
|
|
||||||
try {
|
|
||||||
if (licenseServerKey) {
|
if (licenseServerKey) {
|
||||||
// license server key is present -> validate it
|
// license server key is present -> validate it
|
||||||
const token = await refreshLicenseServerKeyToken()
|
const token = await refreshLicenseServerKeyToken()
|
||||||
@@ -123,11 +121,6 @@ class EELicenseService {
|
|||||||
this.instanceType = 'enterprise-self-hosted';
|
this.instanceType = 'enterprise-self-hosted';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
// case: self-hosted free
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public get isLicenseValid(): boolean {
|
public get isLicenseValid(): boolean {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { Types } from 'mongoose';
|
import { Types } from 'mongoose';
|
||||||
import {
|
import {
|
||||||
Bot,
|
Bot,
|
||||||
@@ -16,7 +15,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
UnauthorizedRequestError,
|
UnauthorizedRequestError,
|
||||||
} from '../utils/errors';
|
} from '../utils/errors';
|
||||||
import RequestError from '../utils/requestError';
|
|
||||||
|
|
||||||
interface Update {
|
interface Update {
|
||||||
workspace: string;
|
workspace: string;
|
||||||
@@ -48,8 +46,6 @@ export const handleOAuthExchangeHelper = async ({
|
|||||||
code: string;
|
code: string;
|
||||||
environment: string;
|
environment: string;
|
||||||
}) => {
|
}) => {
|
||||||
let integrationAuth;
|
|
||||||
try {
|
|
||||||
const bot = await Bot.findOne({
|
const bot = await Bot.findOne({
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
isActive: true
|
isActive: true
|
||||||
@@ -77,7 +73,7 @@ export const handleOAuthExchangeHelper = async ({
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
integrationAuth = await IntegrationAuth.findOneAndUpdate({
|
const integrationAuth = await IntegrationAuth.findOneAndUpdate({
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
integration
|
integration
|
||||||
}, update, {
|
}, update, {
|
||||||
@@ -104,11 +100,6 @@ export const handleOAuthExchangeHelper = async ({
|
|||||||
accessExpiresAt: res.accessExpiresAt
|
accessExpiresAt: res.accessExpiresAt
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error('Failed to handle OAuth2 code-token exchange')
|
|
||||||
}
|
|
||||||
|
|
||||||
return integrationAuth;
|
return integrationAuth;
|
||||||
}
|
}
|
||||||
@@ -125,9 +116,7 @@ export const syncIntegrationsHelper = async ({
|
|||||||
workspaceId: Types.ObjectId;
|
workspaceId: Types.ObjectId;
|
||||||
environment?: string;
|
environment?: string;
|
||||||
}) => {
|
}) => {
|
||||||
let integrations;
|
const integrations = await Integration.find({
|
||||||
try {
|
|
||||||
integrations = await Integration.find({
|
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
...(environment ? {
|
...(environment ? {
|
||||||
environment
|
environment
|
||||||
@@ -162,11 +151,6 @@ export const syncIntegrationsHelper = async ({
|
|||||||
accessToken: access.accessToken
|
accessToken: access.accessToken
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error('Failed to sync secrets to integrations');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -178,31 +162,19 @@ export const syncIntegrationsHelper = async ({
|
|||||||
* @param {String} refreshToken - decrypted refresh token
|
* @param {String} refreshToken - decrypted refresh token
|
||||||
*/
|
*/
|
||||||
export const getIntegrationAuthRefreshHelper = async ({ integrationAuthId }: { integrationAuthId: Types.ObjectId }) => {
|
export const getIntegrationAuthRefreshHelper = async ({ integrationAuthId }: { integrationAuthId: Types.ObjectId }) => {
|
||||||
let refreshToken;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const integrationAuth = await IntegrationAuth
|
const integrationAuth = await IntegrationAuth
|
||||||
.findById(integrationAuthId)
|
.findById(integrationAuthId)
|
||||||
.select('+refreshCiphertext +refreshIV +refreshTag');
|
.select('+refreshCiphertext +refreshIV +refreshTag');
|
||||||
|
|
||||||
if (!integrationAuth) throw UnauthorizedRequestError({message: 'Failed to locate Integration Authentication credentials'});
|
if (!integrationAuth) throw UnauthorizedRequestError({message: 'Failed to locate Integration Authentication credentials'});
|
||||||
|
|
||||||
refreshToken = await BotService.decryptSymmetric({
|
const refreshToken = await BotService.decryptSymmetric({
|
||||||
workspaceId: integrationAuth.workspace,
|
workspaceId: integrationAuth.workspace,
|
||||||
ciphertext: integrationAuth.refreshCiphertext as string,
|
ciphertext: integrationAuth.refreshCiphertext as string,
|
||||||
iv: integrationAuth.refreshIV as string,
|
iv: integrationAuth.refreshIV as string,
|
||||||
tag: integrationAuth.refreshTag as string
|
tag: integrationAuth.refreshTag as string
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
if(err instanceof RequestError)
|
|
||||||
throw err
|
|
||||||
else
|
|
||||||
throw new Error('Failed to get integration refresh token');
|
|
||||||
}
|
|
||||||
|
|
||||||
return refreshToken;
|
return refreshToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +189,6 @@ export const getIntegrationAuthRefreshHelper = async ({ integrationAuthId }: { i
|
|||||||
export const getIntegrationAuthAccessHelper = async ({ integrationAuthId }: { integrationAuthId: Types.ObjectId }) => {
|
export const getIntegrationAuthAccessHelper = async ({ integrationAuthId }: { integrationAuthId: Types.ObjectId }) => {
|
||||||
let accessId;
|
let accessId;
|
||||||
let accessToken;
|
let accessToken;
|
||||||
try {
|
|
||||||
const integrationAuth = await IntegrationAuth
|
const integrationAuth = await IntegrationAuth
|
||||||
.findById(integrationAuthId)
|
.findById(integrationAuthId)
|
||||||
.select('workspace integration +accessCiphertext +accessIV +accessTag +accessExpiresAt + refreshCiphertext +accessIdCiphertext +accessIdIV +accessIdTag');
|
.select('workspace integration +accessCiphertext +accessIV +accessTag +accessExpiresAt + refreshCiphertext +accessIdCiphertext +accessIdIV +accessIdTag');
|
||||||
@@ -254,15 +225,6 @@ export const getIntegrationAuthAccessHelper = async ({ integrationAuthId }: { in
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
if(err instanceof RequestError)
|
|
||||||
throw err
|
|
||||||
else
|
|
||||||
throw new Error('Failed to get integration access token');
|
|
||||||
}
|
|
||||||
|
|
||||||
return ({
|
return ({
|
||||||
accessId,
|
accessId,
|
||||||
accessToken
|
accessToken
|
||||||
@@ -285,9 +247,7 @@ export const setIntegrationAuthRefreshHelper = async ({
|
|||||||
refreshToken: string;
|
refreshToken: string;
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
let integrationAuth;
|
let integrationAuth = await IntegrationAuth
|
||||||
try {
|
|
||||||
integrationAuth = await IntegrationAuth
|
|
||||||
.findById(integrationAuthId);
|
.findById(integrationAuthId);
|
||||||
|
|
||||||
if (!integrationAuth) throw new Error('Failed to find integration auth');
|
if (!integrationAuth) throw new Error('Failed to find integration auth');
|
||||||
@@ -308,11 +268,6 @@ export const setIntegrationAuthRefreshHelper = async ({
|
|||||||
}, {
|
}, {
|
||||||
new: true
|
new: true
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error('Failed to set integration auth refresh token');
|
|
||||||
}
|
|
||||||
|
|
||||||
return integrationAuth;
|
return integrationAuth;
|
||||||
}
|
}
|
||||||
@@ -337,9 +292,7 @@ export const setIntegrationAuthAccessHelper = async ({
|
|||||||
accessToken: string;
|
accessToken: string;
|
||||||
accessExpiresAt: Date | undefined;
|
accessExpiresAt: Date | undefined;
|
||||||
}) => {
|
}) => {
|
||||||
let integrationAuth;
|
let integrationAuth = await IntegrationAuth.findById(integrationAuthId);
|
||||||
try {
|
|
||||||
integrationAuth = await IntegrationAuth.findById(integrationAuthId);
|
|
||||||
|
|
||||||
if (!integrationAuth) throw new Error('Failed to find integration auth');
|
if (!integrationAuth) throw new Error('Failed to find integration auth');
|
||||||
|
|
||||||
@@ -371,11 +324,6 @@ export const setIntegrationAuthAccessHelper = async ({
|
|||||||
}, {
|
}, {
|
||||||
new: true
|
new: true
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error('Failed to save integration auth access token');
|
|
||||||
}
|
|
||||||
|
|
||||||
return integrationAuth;
|
return integrationAuth;
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import * as Sentry from '@sentry/node';
|
import { Types } from "mongoose";
|
||||||
import { Types } from 'mongoose';
|
import { Membership, Key } from "../models";
|
||||||
import { Membership, Key } from '../models';
|
import { MembershipNotFoundError, BadRequestError } from "../utils/errors";
|
||||||
import { MembershipNotFoundError, BadRequestError } from '../utils/errors';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate that user with id [userId] is a member of workspace with id [workspaceId]
|
* Validate that user with id [userId] is a member of workspace with id [workspaceId]
|
||||||
@@ -18,23 +17,23 @@ export const validateMembership = async ({
|
|||||||
}: {
|
}: {
|
||||||
userId: Types.ObjectId | string;
|
userId: Types.ObjectId | string;
|
||||||
workspaceId: Types.ObjectId | string;
|
workspaceId: Types.ObjectId | string;
|
||||||
acceptedRoles?: Array<'admin' | 'member'>;
|
acceptedRoles?: Array<"admin" | "member">;
|
||||||
}) => {
|
}) => {
|
||||||
const membership = await Membership.findOne({
|
const membership = await Membership.findOne({
|
||||||
user: userId,
|
user: userId,
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
}).populate('workspace');
|
}).populate("workspace");
|
||||||
|
|
||||||
if (!membership) {
|
if (!membership) {
|
||||||
throw MembershipNotFoundError({
|
throw MembershipNotFoundError({
|
||||||
message: 'Failed to find workspace membership',
|
message: "Failed to find workspace membership",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (acceptedRoles) {
|
if (acceptedRoles) {
|
||||||
if (!acceptedRoles.includes(membership.role)) {
|
if (!acceptedRoles.includes(membership.role)) {
|
||||||
throw BadRequestError({
|
throw BadRequestError({
|
||||||
message: 'Failed authorization for membership role',
|
message: "Failed authorization for membership role",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,15 +47,7 @@ export const validateMembership = async ({
|
|||||||
* @return {Object} membership - membership
|
* @return {Object} membership - membership
|
||||||
*/
|
*/
|
||||||
export const findMembership = async (queryObj: any) => {
|
export const findMembership = async (queryObj: any) => {
|
||||||
let membership;
|
const membership = await Membership.findOne(queryObj);
|
||||||
try {
|
|
||||||
membership = await Membership.findOne(queryObj);
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error('Failed to find membership');
|
|
||||||
}
|
|
||||||
|
|
||||||
return membership;
|
return membership;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -77,7 +68,6 @@ export const addMemberships = async ({
|
|||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
roles: string[];
|
roles: string[];
|
||||||
}): Promise<void> => {
|
}): Promise<void> => {
|
||||||
try {
|
|
||||||
const operations = userIds.map((userId, idx) => {
|
const operations = userIds.map((userId, idx) => {
|
||||||
return {
|
return {
|
||||||
updateOne: {
|
updateOne: {
|
||||||
@@ -95,13 +85,7 @@ export const addMemberships = async ({
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
await Membership.bulkWrite(operations as any);
|
await Membership.bulkWrite(operations as any);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error('Failed to add users to workspace');
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,9 +94,7 @@ export const addMemberships = async ({
|
|||||||
* @param {String} obj.membershipId - id of membership to delete
|
* @param {String} obj.membershipId - id of membership to delete
|
||||||
*/
|
*/
|
||||||
export const deleteMembership = async ({ membershipId }: { membershipId: string }) => {
|
export const deleteMembership = async ({ membershipId }: { membershipId: string }) => {
|
||||||
let deletedMembership;
|
const deletedMembership = await Membership.findOneAndDelete({
|
||||||
try {
|
|
||||||
deletedMembership = await Membership.findOneAndDelete({
|
|
||||||
_id: membershipId
|
_id: membershipId
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -123,11 +105,6 @@ export const deleteMembership = async ({ membershipId }: { membershipId: string
|
|||||||
receiver: deletedMembership.user,
|
receiver: deletedMembership.user,
|
||||||
workspace: deletedMembership.workspace,
|
workspace: deletedMembership.workspace,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error('Failed to delete membership');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return deletedMembership;
|
return deletedMembership;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import handlebars from 'handlebars';
|
import handlebars from 'handlebars';
|
||||||
@@ -26,7 +25,6 @@ export const sendMail = async ({
|
|||||||
substitutions: any;
|
substitutions: any;
|
||||||
}) => {
|
}) => {
|
||||||
if (await getSmtpConfigured()) {
|
if (await getSmtpConfigured()) {
|
||||||
try {
|
|
||||||
const html = fs.readFileSync(
|
const html = fs.readFileSync(
|
||||||
path.resolve(__dirname, '../templates/' + template),
|
path.resolve(__dirname, '../templates/' + template),
|
||||||
'utf8'
|
'utf8'
|
||||||
@@ -34,17 +32,12 @@ export const sendMail = async ({
|
|||||||
const temp = handlebars.compile(html);
|
const temp = handlebars.compile(html);
|
||||||
const htmlToSend = temp(substitutions);
|
const htmlToSend = temp(substitutions);
|
||||||
|
|
||||||
const x = await smtpTransporter.sendMail({
|
await smtpTransporter.sendMail({
|
||||||
from: `"${await getSmtpFromName()}" <${await getSmtpFromAddress()}>`,
|
from: `"${await getSmtpFromName()}" <${await getSmtpFromAddress()}>`,
|
||||||
to: recipients.join(', '),
|
to: recipients.join(', '),
|
||||||
subject: subjectLine,
|
subject: subjectLine,
|
||||||
html: htmlToSend
|
html: htmlToSend
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -185,18 +185,43 @@ export const generateSecretBlindIndexHelper = async ({
|
|||||||
workspaceId: Types.ObjectId;
|
workspaceId: Types.ObjectId;
|
||||||
}) => {
|
}) => {
|
||||||
// check if workspace blind index data exists
|
// check if workspace blind index data exists
|
||||||
|
const encryptionKey = await getEncryptionKey();
|
||||||
|
const rootEncryptionKey = await getRootEncryptionKey();
|
||||||
|
|
||||||
const secretBlindIndexData = await SecretBlindIndexData.findOne({
|
const secretBlindIndexData = await SecretBlindIndexData.findOne({
|
||||||
workspace: workspaceId,
|
workspace: workspaceId,
|
||||||
});
|
}).select('+algorithm +keyEncoding');
|
||||||
|
|
||||||
if (!secretBlindIndexData) throw SecretBlindIndexDataNotFoundError();
|
if (!secretBlindIndexData) throw SecretBlindIndexDataNotFoundError();
|
||||||
|
|
||||||
|
let salt;
|
||||||
|
if (
|
||||||
|
rootEncryptionKey &&
|
||||||
|
secretBlindIndexData.keyEncoding === ENCODING_SCHEME_BASE64
|
||||||
|
) {
|
||||||
|
salt = client.decryptSymmetric(
|
||||||
|
secretBlindIndexData.encryptedSaltCiphertext,
|
||||||
|
rootEncryptionKey,
|
||||||
|
secretBlindIndexData.saltIV,
|
||||||
|
secretBlindIndexData.saltTag
|
||||||
|
);
|
||||||
|
|
||||||
|
const secretBlindIndex = await generateSecretBlindIndexWithSaltHelper({
|
||||||
|
secretName,
|
||||||
|
salt,
|
||||||
|
});
|
||||||
|
|
||||||
|
return secretBlindIndex;
|
||||||
|
} else if (
|
||||||
|
encryptionKey &&
|
||||||
|
secretBlindIndexData.keyEncoding === ENCODING_SCHEME_UTF8
|
||||||
|
) {
|
||||||
// decrypt workspace salt
|
// decrypt workspace salt
|
||||||
const salt = decryptSymmetric128BitHexKeyUTF8({
|
salt = decryptSymmetric128BitHexKeyUTF8({
|
||||||
ciphertext: secretBlindIndexData.encryptedSaltCiphertext,
|
ciphertext: secretBlindIndexData.encryptedSaltCiphertext,
|
||||||
iv: secretBlindIndexData.saltIV,
|
iv: secretBlindIndexData.saltIV,
|
||||||
tag: secretBlindIndexData.saltTag,
|
tag: secretBlindIndexData.saltTag,
|
||||||
key: await getEncryptionKey(),
|
key: encryptionKey,
|
||||||
});
|
});
|
||||||
|
|
||||||
const secretBlindIndex = await generateSecretBlindIndexWithSaltHelper({
|
const secretBlindIndex = await generateSecretBlindIndexWithSaltHelper({
|
||||||
@@ -205,6 +230,11 @@ export const generateSecretBlindIndexHelper = async ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
return secretBlindIndex;
|
return secretBlindIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw InternalServerError({
|
||||||
|
message: 'Failed to generate secret blind index'
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import { IUser } from '../models';
|
import { IUser } from '../models';
|
||||||
import { createOrganization } from './organization';
|
import { createOrganization } from './organization';
|
||||||
import { addMembershipsOrg } from './membershipOrg';
|
import { addMembershipsOrg } from './membershipOrg';
|
||||||
@@ -15,7 +14,6 @@ import { TOKEN_EMAIL_CONFIRMATION } from '../variables';
|
|||||||
* @returns {Boolean} success - whether or not operation was successful
|
* @returns {Boolean} success - whether or not operation was successful
|
||||||
*/
|
*/
|
||||||
export const sendEmailVerification = async ({ email }: { email: string }) => {
|
export const sendEmailVerification = async ({ email }: { email: string }) => {
|
||||||
try {
|
|
||||||
const token = await TokenService.createToken({
|
const token = await TokenService.createToken({
|
||||||
type: TOKEN_EMAIL_CONFIRMATION,
|
type: TOKEN_EMAIL_CONFIRMATION,
|
||||||
email
|
email
|
||||||
@@ -30,13 +28,6 @@ export const sendEmailVerification = async ({ email }: { email: string }) => {
|
|||||||
code: token
|
code: token
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error(
|
|
||||||
"Ouch. We weren't able to send your email verification code"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,17 +43,11 @@ export const checkEmailVerification = async ({
|
|||||||
email: string;
|
email: string;
|
||||||
code: string;
|
code: string;
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
|
||||||
await TokenService.validateToken({
|
await TokenService.validateToken({
|
||||||
type: TOKEN_EMAIL_CONFIRMATION,
|
type: TOKEN_EMAIL_CONFIRMATION,
|
||||||
email,
|
email,
|
||||||
token: code
|
token: code
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error("Oops. We weren't able to verify");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import * as Sentry from '@sentry/node';
|
|
||||||
import {
|
import {
|
||||||
Workspace,
|
Workspace,
|
||||||
Bot,
|
Bot,
|
||||||
@@ -23,10 +22,8 @@ export const createWorkspace = async ({
|
|||||||
name: string;
|
name: string;
|
||||||
organizationId: string;
|
organizationId: string;
|
||||||
}) => {
|
}) => {
|
||||||
let workspace;
|
|
||||||
try {
|
|
||||||
// create workspace
|
// create workspace
|
||||||
workspace = await new Workspace({
|
const workspace = await new Workspace({
|
||||||
name,
|
name,
|
||||||
organization: organizationId,
|
organization: organizationId,
|
||||||
autoCapitalization: true
|
autoCapitalization: true
|
||||||
@@ -43,11 +40,6 @@ export const createWorkspace = async ({
|
|||||||
workspaceId: workspace._id
|
workspaceId: workspace._id
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error('Failed to create workspace');
|
|
||||||
}
|
|
||||||
|
|
||||||
return workspace;
|
return workspace;
|
||||||
};
|
};
|
||||||
@@ -59,7 +51,6 @@ export const createWorkspace = async ({
|
|||||||
* @param {String} obj.id - id of workspace to delete
|
* @param {String} obj.id - id of workspace to delete
|
||||||
*/
|
*/
|
||||||
export const deleteWorkspace = async ({ id }: { id: string }) => {
|
export const deleteWorkspace = async ({ id }: { id: string }) => {
|
||||||
try {
|
|
||||||
await Workspace.deleteOne({ _id: id });
|
await Workspace.deleteOne({ _id: id });
|
||||||
await Bot.deleteOne({
|
await Bot.deleteOne({
|
||||||
workspace: id
|
workspace: id
|
||||||
@@ -73,9 +64,4 @@ export const deleteWorkspace = async ({ id }: { id: string }) => {
|
|||||||
await Key.deleteMany({
|
await Key.deleteMany({
|
||||||
workspace: id
|
workspace: id
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error('Failed to delete workspace');
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import * as Sentry from "@sentry/node";
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import AWS from 'aws-sdk';
|
import AWS from 'aws-sdk';
|
||||||
import {
|
import {
|
||||||
@@ -61,7 +60,6 @@ const syncSecrets = async ({
|
|||||||
accessId: string | null;
|
accessId: string | null;
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
|
||||||
switch (integration.integration) {
|
switch (integration.integration) {
|
||||||
case INTEGRATION_AZURE_KEY_VAULT:
|
case INTEGRATION_AZURE_KEY_VAULT:
|
||||||
await syncSecretsAzureKeyVault({
|
await syncSecretsAzureKeyVault({
|
||||||
@@ -166,11 +164,6 @@ const syncSecrets = async ({
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error('Failed to sync secrets to integration');
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -189,7 +182,6 @@ const syncSecretsAzureKeyVault = async ({
|
|||||||
secrets: any;
|
secrets: any;
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
|
||||||
interface GetAzureKeyVaultSecret {
|
interface GetAzureKeyVaultSecret {
|
||||||
id: string; // secret URI
|
id: string; // secret URI
|
||||||
attributes: {
|
attributes: {
|
||||||
@@ -212,7 +204,6 @@ const syncSecretsAzureKeyVault = async ({
|
|||||||
*/
|
*/
|
||||||
const paginateAzureKeyVaultSecrets = async (url: string) => {
|
const paginateAzureKeyVaultSecrets = async (url: string) => {
|
||||||
let result: GetAzureKeyVaultSecret[] = [];
|
let result: GetAzureKeyVaultSecret[] = [];
|
||||||
try {
|
|
||||||
while (url) {
|
while (url) {
|
||||||
const res = await standardRequest.get(url, {
|
const res = await standardRequest.get(url, {
|
||||||
headers: {
|
headers: {
|
||||||
@@ -225,11 +216,6 @@ const syncSecretsAzureKeyVault = async ({
|
|||||||
url = res.data.nextLink;
|
url = res.data.nextLink;
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,11 +346,6 @@ const syncSecretsAzureKeyVault = async ({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error('Failed to sync secrets to Azure Key Vault');
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -386,7 +367,6 @@ const syncSecretsAWSParameterStore = async ({
|
|||||||
accessId: string | null;
|
accessId: string | null;
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
|
||||||
if (!accessId) return;
|
if (!accessId) return;
|
||||||
|
|
||||||
AWS.config.update({
|
AWS.config.update({
|
||||||
@@ -462,11 +442,6 @@ const syncSecretsAWSParameterStore = async ({
|
|||||||
accessKeyId: undefined,
|
accessKeyId: undefined,
|
||||||
secretAccessKey: undefined
|
secretAccessKey: undefined
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error('Failed to sync secrets to AWS Parameter Store');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -536,10 +511,6 @@ const syncSecretsAWSSecretManager = async ({
|
|||||||
Name: integration.app,
|
Name: integration.app,
|
||||||
SecretString: JSON.stringify(secrets)
|
SecretString: JSON.stringify(secrets)
|
||||||
}));
|
}));
|
||||||
} else {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error('Failed to sync secrets to AWS Secret Manager');
|
|
||||||
}
|
}
|
||||||
AWS.config.update({
|
AWS.config.update({
|
||||||
region: undefined,
|
region: undefined,
|
||||||
@@ -565,7 +536,6 @@ const syncSecretsHeroku = async ({
|
|||||||
secrets: any;
|
secrets: any;
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
|
||||||
const herokuSecrets = (
|
const herokuSecrets = (
|
||||||
await standardRequest.get(
|
await standardRequest.get(
|
||||||
`${INTEGRATION_HEROKU_API_URL}/apps/${integration.app}/config-vars`,
|
`${INTEGRATION_HEROKU_API_URL}/apps/${integration.app}/config-vars`,
|
||||||
@@ -596,11 +566,6 @@ const syncSecretsHeroku = async ({
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error("Failed to sync secrets to Heroku");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -628,8 +593,6 @@ const syncSecretsVercel = async ({
|
|||||||
target: string[];
|
target: string[];
|
||||||
gitBranch?: string;
|
gitBranch?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
// Get all (decrypted) secrets back from Vercel in
|
// Get all (decrypted) secrets back from Vercel in
|
||||||
// decrypted format
|
// decrypted format
|
||||||
const params: { [key: string]: string } = {
|
const params: { [key: string]: string } = {
|
||||||
@@ -788,11 +751,6 @@ const syncSecretsVercel = async ({
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error("Failed to sync secrets to Vercel");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -814,7 +772,6 @@ const syncSecretsNetlify = async ({
|
|||||||
secrets: any;
|
secrets: any;
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
|
||||||
interface NetlifyValue {
|
interface NetlifyValue {
|
||||||
id?: string;
|
id?: string;
|
||||||
context: string; // 'dev' | 'branch-deploy' | 'deploy-preview' | 'production',
|
context: string; // 'dev' | 'branch-deploy' | 'deploy-preview' | 'production',
|
||||||
@@ -1011,11 +968,6 @@ const syncSecretsNetlify = async ({
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error("Failed to sync secrets to Heroku");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1035,7 +987,6 @@ const syncSecretsGitHub = async ({
|
|||||||
secrets: any;
|
secrets: any;
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
|
||||||
interface GitHubRepoKey {
|
interface GitHubRepoKey {
|
||||||
key_id: string;
|
key_id: string;
|
||||||
key: string;
|
key: string;
|
||||||
@@ -1126,11 +1077,6 @@ const syncSecretsGitHub = async ({
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error("Failed to sync secrets to GitHub");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1149,7 +1095,6 @@ const syncSecretsRender = async ({
|
|||||||
secrets: any;
|
secrets: any;
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
|
||||||
await standardRequest.put(
|
await standardRequest.put(
|
||||||
`${INTEGRATION_RENDER_API_URL}/v1/services/${integration.appId}/env-vars`,
|
`${INTEGRATION_RENDER_API_URL}/v1/services/${integration.appId}/env-vars`,
|
||||||
Object.keys(secrets).map((key) => ({
|
Object.keys(secrets).map((key) => ({
|
||||||
@@ -1163,11 +1108,6 @@ const syncSecretsRender = async ({
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error("Failed to sync secrets to Render");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1186,8 +1126,6 @@ const syncSecretsRailway = async ({
|
|||||||
secrets: any;
|
secrets: any;
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
|
||||||
|
|
||||||
const query = `
|
const query = `
|
||||||
mutation UpsertVariables($input: VariableCollectionUpsertInput!) {
|
mutation UpsertVariables($input: VariableCollectionUpsertInput!) {
|
||||||
variableCollectionUpsert(input: $input)
|
variableCollectionUpsert(input: $input)
|
||||||
@@ -1214,12 +1152,6 @@ const syncSecretsRailway = async ({
|
|||||||
'Accept-Encoding': 'application/json'
|
'Accept-Encoding': 'application/json'
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error("Failed to sync secrets to Railway");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1238,7 +1170,6 @@ const syncSecretsFlyio = async ({
|
|||||||
secrets: any;
|
secrets: any;
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
|
||||||
// set secrets
|
// set secrets
|
||||||
const SetSecrets = `
|
const SetSecrets = `
|
||||||
mutation($input: SetSecretsInput!) {
|
mutation($input: SetSecretsInput!) {
|
||||||
@@ -1346,12 +1277,6 @@ const syncSecretsFlyio = async ({
|
|||||||
'Accept-Encoding': 'application/json',
|
'Accept-Encoding': 'application/json',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error("Failed to sync secrets to Fly.io");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1370,7 +1295,6 @@ const syncSecretsCircleCI = async ({
|
|||||||
secrets: any;
|
secrets: any;
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
|
||||||
const circleciOrganizationDetail = (
|
const circleciOrganizationDetail = (
|
||||||
await standardRequest.get(`${INTEGRATION_CIRCLECI_API_URL}/v2/me/collaborations`, {
|
await standardRequest.get(`${INTEGRATION_CIRCLECI_API_URL}/v2/me/collaborations`, {
|
||||||
headers: {
|
headers: {
|
||||||
@@ -1427,11 +1351,6 @@ const syncSecretsCircleCI = async ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error("Failed to sync secrets to CircleCI");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1450,7 +1369,6 @@ const syncSecretsTravisCI = async ({
|
|||||||
secrets: any;
|
secrets: any;
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
|
||||||
// get secrets from travis-ci
|
// get secrets from travis-ci
|
||||||
const getSecretsRes = (
|
const getSecretsRes = (
|
||||||
await standardRequest.get(
|
await standardRequest.get(
|
||||||
@@ -1528,11 +1446,6 @@ const syncSecretsTravisCI = async ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error("Failed to sync secrets to GitLab");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1552,7 +1465,6 @@ const syncSecretsGitLab = async ({
|
|||||||
secrets: any;
|
secrets: any;
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
|
||||||
interface GitLabSecret {
|
interface GitLabSecret {
|
||||||
key: string;
|
key: string;
|
||||||
value: string;
|
value: string;
|
||||||
@@ -1646,12 +1558,6 @@ const syncSecretsGitLab = async ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error("Failed to sync secrets to GitLab");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1671,7 +1577,6 @@ const syncSecretsSupabase = async ({
|
|||||||
secrets: any;
|
secrets: any;
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
|
||||||
const { data: getSecretsRes } = await standardRequest.get(
|
const { data: getSecretsRes } = await standardRequest.get(
|
||||||
`${INTEGRATION_SUPABASE_API_URL}/v1/projects/${integration.appId}/secrets`,
|
`${INTEGRATION_SUPABASE_API_URL}/v1/projects/${integration.appId}/secrets`,
|
||||||
{
|
{
|
||||||
@@ -1721,11 +1626,6 @@ const syncSecretsSupabase = async ({
|
|||||||
data: secretsToDelete
|
data: secretsToDelete
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
Sentry.captureException(err);
|
|
||||||
throw new Error('Failed to sync secrets to Supabase');
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
@@ -43,4 +43,5 @@ export interface BatchSecret {
|
|||||||
secretCommentIV: string;
|
secretCommentIV: string;
|
||||||
secretCommentTag: string;
|
secretCommentTag: string;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
|
folder: string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -335,6 +335,33 @@ export const backfillSecretFolders = async () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await SecretVersion.updateMany(
|
||||||
|
{
|
||||||
|
folder: {
|
||||||
|
$exists: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$set: {
|
||||||
|
folder: "root",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Back fill because tags were missing in secret versions
|
||||||
|
await SecretVersion.updateMany(
|
||||||
|
{
|
||||||
|
tags: {
|
||||||
|
$exists: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$set: {
|
||||||
|
tags: [],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
let secretSnapshots = await SecretSnapshot.find({
|
let secretSnapshots = await SecretSnapshot.find({
|
||||||
environment: {
|
environment: {
|
||||||
$exists: false,
|
$exists: false,
|
||||||
@@ -352,12 +379,15 @@ export const backfillSecretFolders = async () => {
|
|||||||
groupSnapByEnv[secVer.environment].push(secVer);
|
groupSnapByEnv[secVer.environment].push(secVer);
|
||||||
});
|
});
|
||||||
|
|
||||||
const newSnapshots = Object.keys(groupSnapByEnv).map((snapEnv) => ({
|
const newSnapshots = Object.keys(groupSnapByEnv).map((snapEnv) => {
|
||||||
|
const secretIdsOfEnvGroup = groupSnapByEnv[snapEnv] ? groupSnapByEnv[snapEnv].map(secretVersion => secretVersion._id) : []
|
||||||
|
return {
|
||||||
...secSnapshot.toObject({ virtuals: false }),
|
...secSnapshot.toObject({ virtuals: false }),
|
||||||
_id: new Types.ObjectId(),
|
_id: new Types.ObjectId(),
|
||||||
environment: snapEnv,
|
environment: snapEnv,
|
||||||
secretVersions: groupSnapByEnv[snapEnv],
|
secretVersions: secretIdsOfEnvGroup,
|
||||||
}));
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await SecretSnapshot.insertMany(newSnapshots);
|
await SecretSnapshot.insertMany(newSnapshots);
|
||||||
await secSnapshot.delete();
|
await secSnapshot.delete();
|
||||||
|
|||||||
@@ -29,20 +29,20 @@ export const validateEncryptionKeysConfig = async () => {
|
|||||||
message: "Failed to find required root encryption key environment variable. Please make sure that you're passing in a ROOT_ENCRYPTION_KEY environment variable."
|
message: "Failed to find required root encryption key environment variable. Please make sure that you're passing in a ROOT_ENCRYPTION_KEY environment variable."
|
||||||
});
|
});
|
||||||
|
|
||||||
if (encryptionKey && encryptionKey !== '') {
|
// if (encryptionKey && encryptionKey !== '') {
|
||||||
// validate [encryptionKey]
|
// // validate [encryptionKey]
|
||||||
|
|
||||||
const keyBuffer = Buffer.from(encryptionKey, 'hex');
|
// const keyBuffer = Buffer.from(encryptionKey, 'hex');
|
||||||
const decoded = keyBuffer.toString('hex');
|
// const decoded = keyBuffer.toString('hex');
|
||||||
|
|
||||||
if (decoded !== encryptionKey) throw InternalServerError({
|
// if (decoded !== encryptionKey) throw InternalServerError({
|
||||||
message: 'Failed to validate that the encryption key is correctly encoded in hex.'
|
// message: 'Failed to validate that the encryption key is correctly encoded in hex.'
|
||||||
});
|
// });
|
||||||
|
|
||||||
if (keyBuffer.length !== 16) throw InternalServerError({
|
// if (keyBuffer.length !== 16) throw InternalServerError({
|
||||||
message: 'Failed to validate that the encryption key is a 128-bit hex string.'
|
// message: 'Failed to validate that the encryption key is a 128-bit hex string.'
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (rootEncryptionKey && rootEncryptionKey !== '') {
|
if (rootEncryptionKey && rootEncryptionKey !== '') {
|
||||||
// validate [rootEncryptionKey]
|
// validate [rootEncryptionKey]
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ export const validateClientForWorkspace = async ({
|
|||||||
requiredPermissions?: string[];
|
requiredPermissions?: string[];
|
||||||
requireBlindIndicesEnabled: boolean;
|
requireBlindIndicesEnabled: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
const workspace = await Workspace.findById(workspaceId);
|
const workspace = await Workspace.findById(workspaceId);
|
||||||
|
|
||||||
if (!workspace) throw WorkspaceNotFoundError({
|
if (!workspace) throw WorkspaceNotFoundError({
|
||||||
|
|||||||
@@ -121,12 +121,6 @@
|
|||||||
{
|
{
|
||||||
"group": "Self-host Infisical",
|
"group": "Self-host Infisical",
|
||||||
"pages": [
|
"pages": [
|
||||||
{
|
|
||||||
"group": "Authentication",
|
|
||||||
"pages": [
|
|
||||||
"self-hosting/authentication/google"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"group": "Deployment options",
|
"group": "Deployment options",
|
||||||
"pages": [
|
"pages": [
|
||||||
|
|||||||
@@ -3,17 +3,15 @@ title: "Configure email service"
|
|||||||
description: "How to configure your email when self-hosting Infisical."
|
description: "How to configure your email when self-hosting Infisical."
|
||||||
---
|
---
|
||||||
|
|
||||||
Infisical requires you to configure your own SMTP server for certain functionality like:
|
By default, the core functions of Infisical work without any email service configuration. Without email service, the following functionality will be deactivated.
|
||||||
|
|
||||||
- Sending email confirmation links to sign up.
|
- Sending email confirmation links to sign up.
|
||||||
- Sending invite links for projects.
|
- Sending invite links for projects.
|
||||||
- Sending alerts.
|
- Sending alerts.
|
||||||
|
|
||||||
We strongly recommend using an email service to act as your email server and provide examples for common providers.
|
|
||||||
|
|
||||||
## General configuration
|
## General configuration
|
||||||
|
|
||||||
By default, you need to configure the following SMTP [environment variables](https://infisical.com/docs/self-hosting/configuration/envars):
|
If you choose to setup email service, yuu need to configure the following SMTP [environment variables](https://infisical.com/docs/self-hosting/configuration/envars):
|
||||||
|
|
||||||
- `SMTP_HOST`: Hostname to connect to for establishing SMTP connections.
|
- `SMTP_HOST`: Hostname to connect to for establishing SMTP connections.
|
||||||
- `SMTP_USERNAME`: Credential to connect to host (e.g. [email protected])
|
- `SMTP_USERNAME`: Credential to connect to host (e.g. [email protected])
|
||||||
|
|||||||
@@ -1,19 +1,65 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
import attemptLogin from '@app/components/utilities/attemptLogin';
|
||||||
|
|
||||||
|
import Error from '../basic/Error';
|
||||||
// import { faGoogle } from '@fortawesome/free-brands-svg-icons';
|
// import { faGoogle } from '@fortawesome/free-brands-svg-icons';
|
||||||
// import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
// import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { Button } from '../v2';
|
import { Button, Input } from '../v2';
|
||||||
|
|
||||||
export default function InitialLoginStep({
|
export default function InitialLoginStep({
|
||||||
setIsLoginWithEmail,
|
setStep,
|
||||||
|
email,
|
||||||
|
setEmail,
|
||||||
|
password,
|
||||||
|
setPassword,
|
||||||
}: {
|
}: {
|
||||||
setIsLoginWithEmail: (value: boolean) => void;
|
setStep: (step: number) => void;
|
||||||
|
email: string;
|
||||||
|
setEmail: (email: string) => void;
|
||||||
|
password: string;
|
||||||
|
setPassword: (password: string) => void;
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [loginError, setLoginError] = useState(false);
|
||||||
|
|
||||||
|
const handleLogin = async () => {
|
||||||
|
try {
|
||||||
|
if (!email || !password) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsLoading(true);
|
||||||
|
const isLoginSuccessful = await attemptLogin({
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
});
|
||||||
|
if (isLoginSuccessful && isLoginSuccessful.success) {
|
||||||
|
// case: login was successful
|
||||||
|
|
||||||
|
if (isLoginSuccessful.mfaEnabled) {
|
||||||
|
// case: login requires MFA step
|
||||||
|
setStep(2);
|
||||||
|
setIsLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// case: login does not require MFA step
|
||||||
|
router.push(`/dashboard/${localStorage.getItem('projectData.id')}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
setLoginError(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
|
||||||
return <div className='flex flex-col mx-auto w-full justify-center items-center'>
|
return <div className='flex flex-col mx-auto w-full justify-center items-center'>
|
||||||
<h1 className='text-xl font-medium text-transparent bg-clip-text bg-gradient-to-b from-white to-bunker-200 text-center mb-8' >Login to Infisical</h1>
|
<h1 className='text-xl font-medium text-transparent bg-clip-text bg-gradient-to-b from-white to-bunker-200 text-center mb-8' >Login to Infisical</h1>
|
||||||
@@ -30,18 +76,49 @@ export default function InitialLoginStep({
|
|||||||
{t('login.continue-with-google')}
|
{t('login.continue-with-google')}
|
||||||
</Button>
|
</Button>
|
||||||
</div> */}
|
</div> */}
|
||||||
<div className='lg:w-1/6 w-1/4 min-w-[20rem] text-center rounded-md'>
|
<div className="relative md:px-1.5 flex items-center justify-center lg:w-1/6 w-1/4 min-w-[20rem] md:min-w-[22rem] mx-auto w-full rounded-lg max-h-24 md:max-h-28">
|
||||||
|
<div className="flex items-center justify-center w-full md:px-2 md:py-1 rounded-lg max-h-24 md:max-h-28">
|
||||||
|
<Input
|
||||||
|
value={email}
|
||||||
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
|
type="email"
|
||||||
|
placeholder="Enter your email..."
|
||||||
|
isRequired
|
||||||
|
autoComplete="username"
|
||||||
|
className="h-12"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="relative pt-2 md:pt-0 md:px-1.5 flex items-center justify-center lg:w-1/6 w-1/4 min-w-[20rem] md:min-w-[22rem] mx-auto w-full rounded-lg max-h-24 md:max-h-28">
|
||||||
|
<div className="flex items-center justify-center w-full md:p-2 rounded-lg max-h-24 md:max-h-28">
|
||||||
|
<Input
|
||||||
|
value={password}
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
|
type="password"
|
||||||
|
placeholder="Enter your password..."
|
||||||
|
isRequired
|
||||||
|
autoComplete="current-password"
|
||||||
|
id="current-password"
|
||||||
|
className="h-12 select:-webkit-autofill:focus"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{!isLoading && loginError && <Error text={t('login.error-login') ?? ''} />}
|
||||||
|
<div className='lg:w-1/6 w-1/4 min-w-[21.2rem] md:min-w-[20.1rem] text-center rounded-md mt-4'>
|
||||||
<Button
|
<Button
|
||||||
|
onClick={async () => handleLogin()}
|
||||||
|
size="sm"
|
||||||
|
isFullWidth
|
||||||
|
className='h-12'
|
||||||
colorSchema="primary"
|
colorSchema="primary"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
onClick={() => {
|
isLoading={isLoading}
|
||||||
setIsLoginWithEmail(true);
|
> Login </Button>
|
||||||
}}
|
</div>
|
||||||
isFullWidth
|
<div className='lg:w-1/6 w-1/4 min-w-[20rem] flex flex-row items-center mt-4 py-2'>
|
||||||
className="h-14 w-full mx-0"
|
<div className='w-1/2 border-t border-mineshaft-500'/>
|
||||||
>
|
<span className='px-4 text-sm text-bunker-400'>or</span>
|
||||||
{t('login.continue-with-email')}
|
<div className='w-1/2 border-t border-mineshaft-500'/>
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
<div className='lg:w-1/6 w-1/4 min-w-[20rem] text-center rounded-md mt-4'>
|
<div className='lg:w-1/6 w-1/4 min-w-[20rem] text-center rounded-md mt-4'>
|
||||||
<Button
|
<Button
|
||||||
@@ -54,7 +131,7 @@ export default function InitialLoginStep({
|
|||||||
Continue with SAML SSO
|
Continue with SAML SSO
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4 text-bunker-400 text-sm flex flex-row">
|
<div className="mt-6 text-bunker-400 text-sm flex flex-row">
|
||||||
<span className="mr-1">Don't have an acount yet?</span>
|
<span className="mr-1">Don't have an acount yet?</span>
|
||||||
<Link href="/signup">
|
<Link href="/signup">
|
||||||
<span className='hover:underline hover:underline-offset-4 hover:decoration-primary-700 hover:text-bunker-200 duration-200 cursor-pointer'>{t('login.create-account')}</span>
|
<span className='hover:underline hover:underline-offset-4 hover:decoration-primary-700 hover:text-bunker-200 duration-200 cursor-pointer'>{t('login.create-account')}</span>
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ const props = {
|
|||||||
fontFamily: 'monospace',
|
fontFamily: 'monospace',
|
||||||
margin: '4px',
|
margin: '4px',
|
||||||
MozAppearance: 'textfield',
|
MozAppearance: 'textfield',
|
||||||
width: '55px',
|
width: '48px',
|
||||||
borderRadius: '5px',
|
borderRadius: '5px',
|
||||||
fontSize: '24px',
|
fontSize: '24px',
|
||||||
height: '55px',
|
height: '48px',
|
||||||
paddingLeft: '7',
|
paddingLeft: '7',
|
||||||
backgroundColor: '#0d1117',
|
backgroundColor: '#0d1117',
|
||||||
color: 'white',
|
color: 'white',
|
||||||
@@ -115,7 +115,7 @@ export default function MFAStep({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className="mx-auto w-max px-8 pb-4 pt-4 md:mb-16">
|
<form className="mx-auto w-max md:px-8 pb-4 pt-4 md:mb-16">
|
||||||
<p className="text-l flex justify-center text-bunker-300">{t('mfa.step2-message')}</p>
|
<p className="text-l flex justify-center text-bunker-300">{t('mfa.step2-message')}</p>
|
||||||
<p className="text-l my-1 flex justify-center font-semibold text-bunker-300">{email} </p>
|
<p className="text-l my-1 flex justify-center font-semibold text-bunker-300">{email} </p>
|
||||||
<div className="hidden md:block w-max min-w-[20rem] mx-auto">
|
<div className="hidden md:block w-max min-w-[20rem] mx-auto">
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ export default function CodeInputStep({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto h-full w-full pb-4 px-8">
|
<div className="mx-auto h-full w-full pb-4 md:px-8">
|
||||||
<p className="text-md flex justify-center text-bunker-200">{t('signup.step2-message')}</p>
|
<p className="text-md flex justify-center text-bunker-200">{t('signup.step2-message')}</p>
|
||||||
<p className="text-md flex justify-center font-semibold my-1 text-bunker-200">{email} </p>
|
<p className="text-md flex justify-center font-semibold my-1 text-bunker-200">{email} </p>
|
||||||
<div className="hidden md:block w-max min-w-[20rem] mx-auto">
|
<div className="hidden md:block w-max min-w-[20rem] mx-auto">
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export default function DonwloadBackupPDFStep({
|
|||||||
<p className="text-xl text-center font-medium flex justify-center text-transparent bg-clip-text bg-gradient-to-b from-white to-bunker-200">
|
<p className="text-xl text-center font-medium flex justify-center text-transparent bg-clip-text bg-gradient-to-b from-white to-bunker-200">
|
||||||
<FontAwesomeIcon icon={faWarning} className="ml-2 mr-3 pt-1 text-2xl text-bunker-200" />{t('signup.step4-message')}
|
<FontAwesomeIcon icon={faWarning} className="ml-2 mr-3 pt-1 text-2xl text-bunker-200" />{t('signup.step4-message')}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex flex-col pb-2 bg-mineshaft-900 border border-mineshaft-700 items-center justify-center text-center lg:w-1/6 w-full md:min-w-[24rem] mt-8 max-w-md text-bunker-300 text-md rounded-md">
|
<div className="flex flex-col pb-2 bg-mineshaft-800 border border-mineshaft-600 items-center justify-center text-center lg:w-1/6 w-full md:min-w-[24rem] mt-8 max-w-md text-bunker-300 text-md rounded-md">
|
||||||
<div className="w-full mt-4 md:mt-8 flex flex-row text-center items-center m-2 text-bunker-300 rounded-md lg:w-1/6 lg:w-1/6 w-full md:min-w-[23rem] px-3 mx-auto">
|
<div className="w-full mt-4 md:mt-8 flex flex-row text-center items-center m-2 text-bunker-300 rounded-md lg:w-1/6 lg:w-1/6 w-full md:min-w-[23rem] px-3 mx-auto">
|
||||||
<span className='mb-2'>{t('signup.step4-description1')} {t('signup.step4-description3')}</span>
|
<span className='mb-2'>{t('signup.step4-description1')} {t('signup.step4-description3')}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export default function InitialSignupStep({
|
|||||||
isFullWidth
|
isFullWidth
|
||||||
className="h-14 w-full mx-0"
|
className="h-14 w-full mx-0"
|
||||||
>
|
>
|
||||||
{t('signup.continue-with-email')}
|
Sign Up with email
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className='lg:w-1/6 w-1/4 min-w-[20rem] text-center rounded-md mt-4'>
|
<div className='lg:w-1/6 w-1/4 min-w-[20rem] text-center rounded-md mt-4'>
|
||||||
|
|||||||
@@ -217,11 +217,11 @@ export default function UserInfoStep({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full mx-auto mb-36 w-max rounded-xl px-8 md:mb-16">
|
<div className="h-full mx-auto mb-36 w-max rounded-xl md:px-8 md:mb-16">
|
||||||
<p className="mx-8 mb-6 flex justify-center text-xl font-bold text-medium md:mx-16 text-transparent bg-clip-text bg-gradient-to-b from-white to-bunker-200">
|
<p className="mx-8 mb-6 flex justify-center text-xl font-bold text-medium md:mx-16 text-transparent bg-clip-text bg-gradient-to-b from-white to-bunker-200">
|
||||||
{t('signup.step3-message')}
|
{t('signup.step3-message')}
|
||||||
</p>
|
</p>
|
||||||
<div className="h-full mx-auto mb-36 w-max rounded-xl py-6 px-8 md:mb-16 border border-mineshaft-600 bg-mineshaft-800">
|
<div className="h-full mx-auto mb-36 w-max rounded-xl py-6 md:px-8 md:mb-16 md:border md:border-mineshaft-600 md:bg-mineshaft-800">
|
||||||
<div className="relative z-0 lg:w-1/6 w-1/4 min-w-[20rem] flex flex-col items-center justify-end w-full py-2 rounded-lg">
|
<div className="relative z-0 lg:w-1/6 w-1/4 min-w-[20rem] flex flex-col items-center justify-end w-full py-2 rounded-lg">
|
||||||
<p className='text-left w-full text-sm text-bunker-300 mb-1 ml-1 font-medium'>Your Name</p>
|
<p className='text-left w-full text-sm text-bunker-300 mb-1 ml-1 font-medium'>Your Name</p>
|
||||||
<Input
|
<Input
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { useRouter } from 'next/router';
|
|||||||
|
|
||||||
// import ListBox from '@app/components/basic/Listbox';
|
// import ListBox from '@app/components/basic/Listbox';
|
||||||
import InitialLoginStep from '@app/components/login/InitialLoginStep';
|
import InitialLoginStep from '@app/components/login/InitialLoginStep';
|
||||||
import LoginStep from '@app/components/login/LoginStep';
|
|
||||||
import MFAStep from '@app/components/login/MFAStep';
|
import MFAStep from '@app/components/login/MFAStep';
|
||||||
import PasswordInputStep from '@app/components/login/PasswordInputStep';
|
import PasswordInputStep from '@app/components/login/PasswordInputStep';
|
||||||
import { useProviderAuth } from '@app/hooks/useProviderAuth';
|
import { useProviderAuth } from '@app/hooks/useProviderAuth';
|
||||||
@@ -22,7 +21,6 @@ export default function Login() {
|
|||||||
const [step, setStep] = useState(1);
|
const [step, setStep] = useState(1);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
// const lang = router.locale ?? 'en';
|
// const lang = router.locale ?? 'en';
|
||||||
const [isLoginWithEmail, setIsLoginWithEmail] = useState(false);
|
|
||||||
const {
|
const {
|
||||||
providerAuthToken,
|
providerAuthToken,
|
||||||
email: providerEmail,
|
email: providerEmail,
|
||||||
@@ -70,20 +68,14 @@ export default function Login() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLoginWithEmail && loginStep === 1) {
|
if (loginStep === 1) {
|
||||||
return (
|
return <InitialLoginStep
|
||||||
<LoginStep
|
setStep={setStep}
|
||||||
email={email}
|
email={email}
|
||||||
setEmail={setEmail}
|
setEmail={setEmail}
|
||||||
password={password}
|
password={password}
|
||||||
setPassword={setPassword}
|
setPassword={setPassword}
|
||||||
setStep={setStep}
|
/>;
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isLoginWithEmail && loginStep === 1) {
|
|
||||||
return <InitialLoginStep setIsLoginWithEmail={setIsLoginWithEmail} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (step === 2) {
|
if (step === 2) {
|
||||||
|
|||||||
@@ -46,16 +46,16 @@ export default function Login() {
|
|||||||
<Image src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical logo" />
|
<Image src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical logo" />
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
<div className="mx-auto w-full max-w-md px-6">
|
<div className="mx-auto w-full max-w-md md:px-6">
|
||||||
<p className="mx-auto mb-6 flex w-max justify-center text-xl font-medium text-transparent bg-clip-text bg-gradient-to-b from-white to-bunker-200 text-center mb-8">
|
<p className="mx-auto mb-6 flex w-max justify-center text-xl font-medium text-transparent bg-clip-text bg-gradient-to-b from-white to-bunker-200 text-center mb-8">
|
||||||
What’s your email?
|
What’s your email?
|
||||||
</p>
|
</p>
|
||||||
<div className="relative flex items-center justify-center lg:w-1/6 w-1/4 min-w-[22rem] mx-auto w-full rounded-lg max-h-24 md:max-h-28">
|
<div className="relative flex items-center justify-center lg:w-1/6 w-1/4 min-w-[20rem] md:min-w-[22rem] mx-auto w-full rounded-lg max-h-24 md:max-h-28">
|
||||||
<div className="flex items-center justify-center w-full rounded-lg max-h-24 md:max-h-28">
|
<div className="flex items-center justify-center w-full rounded-lg max-h-24 md:max-h-28">
|
||||||
<Input
|
<Input
|
||||||
value={password}
|
value={password}
|
||||||
onChange={(e) => setPassword(e.target.value)}
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
type="password"
|
type="email"
|
||||||
placeholder="Enter your email..."
|
placeholder="Enter your email..."
|
||||||
isRequired
|
isRequired
|
||||||
autoComplete="email"
|
autoComplete="email"
|
||||||
@@ -64,7 +64,7 @@ export default function Login() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='lg:w-1/6 w-1/4 w-full mx-auto flex items-center justify-center min-w-[22rem] text-center rounded-md mt-4'>
|
<div className='lg:w-1/6 w-1/4 w-full mx-auto flex items-center justify-center min-w-[20rem] md:min-w-[22rem] text-center rounded-md mt-4'>
|
||||||
<Button
|
<Button
|
||||||
colorSchema="primary"
|
colorSchema="primary"
|
||||||
variant="outline_bg"
|
variant="outline_bg"
|
||||||
|
|||||||
@@ -717,9 +717,9 @@ export const DashboardPage = ({ envFromTop }: { envFromTop: string }) => {
|
|||||||
isLoading={isSubmitting}
|
isLoading={isSubmitting}
|
||||||
leftIcon={<FontAwesomeIcon icon={isRollbackMode ? faClockRotateLeft : faCheck} />}
|
leftIcon={<FontAwesomeIcon icon={isRollbackMode ? faClockRotateLeft : faCheck} />}
|
||||||
onClick={handleSubmit(onSaveSecret)}
|
onClick={handleSubmit(onSaveSecret)}
|
||||||
className="h-10"
|
className="h-10 text-black"
|
||||||
color="primary"
|
color="primary"
|
||||||
variant="star"
|
variant="solid"
|
||||||
>
|
>
|
||||||
{isRollbackMode ? 'Rollback' : 'Save Changes'}
|
{isRollbackMode ? 'Rollback' : 'Save Changes'}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
Reference in New Issue
Block a user