Merge branch 'main' into feature/google-signin-signup-integration

This commit is contained in:
Sheen Capadngan
2023-05-24 18:39:18 +08:00
40 changed files with 1188 additions and 322 deletions
@@ -16,7 +16,7 @@ import {
INTEGRATION_VERCEL_API_URL,
INTEGRATION_RAILWAY_API_URL
} from '../../variables';
import request from '../../config/request';
import { standardRequest } from '../../config/request';
/***
* Return integration authorization with id [integrationAuthId]
@@ -229,7 +229,7 @@ export const getIntegrationAuthVercelBranches = async (req: Request, res: Respon
let branches: string[] = [];
if (appId && appId !== '') {
const { data }: { data: VercelBranch[] } = await request.get(
const { data }: { data: VercelBranch[] } = await standardRequest.get(
`${INTEGRATION_VERCEL_API_URL}/v1/integrations/git-branches`,
{
params,
@@ -292,7 +292,7 @@ export const getIntegrationAuthRailwayEnvironments = async (req: Request, res: R
projectId: appId
}
const { data: { data: { environments: { edges } } } } = await request.post(INTEGRATION_RAILWAY_API_URL, {
const { data: { data: { environments: { edges } } } } = await standardRequest.post(INTEGRATION_RAILWAY_API_URL, {
query,
variables,
}, {
@@ -372,7 +372,7 @@ export const getIntegrationAuthRailwayServices = async (req: Request, res: Respo
id: appId
}
const { data: { data: { project: { services: { edges } } } } } = await request.post(INTEGRATION_RAILWAY_API_URL, {
const { data: { data: { project: { services: { edges } } } } } = await standardRequest.post(INTEGRATION_RAILWAY_API_URL, {
query,
variables
}, {
@@ -135,6 +135,7 @@ export const inviteUserToOrganization = async (req: Request, res: Response) => {
}
if (!inviteeMembershipOrg) {
await new MembershipOrg({
user: invitee,
inviteEmail: inviteeEmail,
@@ -246,6 +247,10 @@ export const verifyUserToOrganization = async (req: Request, res: Response) => {
// membership can be approved and redirected to login/dashboard
membershipOrg.status = ACCEPTED;
await membershipOrg.save();
await updateSubscriptionOrgQuantity({
organizationId
});
return res.status(200).send({
message: 'Successfully verified email',
@@ -21,14 +21,6 @@ export const beginEmailSignup = async (req: Request, res: Response) => {
try {
email = req.body.email;
if (await getInviteOnlySignup()) {
// Only one user can create an account without being invited. The rest need to be invited in order to make an account
const userCount = await User.countDocuments({})
if (userCount != 0) {
throw BadRequestError({ message: "New user sign ups are not allowed at this time. You must be invited to sign up." })
}
}
const user = await User.findOne({ email }).select('+publicKey');
if (user && user?.publicKey) {
// case: user has already completed account
@@ -74,6 +66,14 @@ export const verifyEmailSignup = async (req: Request, res: Response) => {
});
}
if (await getInviteOnlySignup()) {
// Only one user can create an account without being invited. The rest need to be invited in order to make an account
const userCount = await User.countDocuments({})
if (userCount != 0) {
throw BadRequestError({ message: "New user sign ups are not allowed at this time. You must be invited to sign up." })
}
}
// verify email
if (await getSmtpConfigured()) {
await checkEmailVerification({
+50 -13
View File
@@ -1,26 +1,24 @@
import to from 'await-to-js';
import { Types } from 'mongoose';
import { Request, Response } from 'express';
import { ISecret, Secret } from '../../models';
import { ISecret, Secret, Workspace } from '../../models';
import { IAction, SecretVersion } from '../../ee/models';
import {
SECRET_PERSONAL,
SECRET_SHARED,
ACTION_ADD_SECRETS,
ACTION_READ_SECRETS,
ACTION_UPDATE_SECRETS,
ACTION_DELETE_SECRETS
} from '../../variables';
import { UnauthorizedRequestError, ValidationError } from '../../utils/errors';
import { UnauthorizedRequestError, WorkspaceNotFoundError } from '../../utils/errors';
import { EventService } from '../../services';
import { eventPushSecrets } from '../../events';
import { EESecretService, EELogService } from '../../ee/services';
import { EESecretService, EELogService, EELicenseService } from '../../ee/services';
import { TelemetryService, SecretService } from '../../services';
import { getChannelFromUserAgent } from '../../utils/posthog';
import { PERMISSION_WRITE_SECRETS } from '../../variables';
import { userHasNoAbility, userHasWorkspaceAccess, userHasWriteOnlyAbility } from '../../ee/helpers/checkMembershipPermissions';
import Tag from '../../models/tag';
import _, { eq } from 'lodash';
import _ from 'lodash';
import {
BatchSecretRequest,
BatchSecret
@@ -48,6 +46,12 @@ export const batchSecrets = async (req: Request, res: Response) => {
environment: string;
requests: BatchSecretRequest[];
} = req.body;
const workspace = await Workspace.findById(workspaceId);
if (!workspace) throw WorkspaceNotFoundError();
const orgPlan = await EELicenseService.getOrganizationPlan(workspace.organization.toString());
const isPaid = orgPlan.tier < 1;
const createSecrets: BatchSecret[] = [];
const updateSecrets: BatchSecret[] = [];
@@ -139,7 +143,8 @@ export const batchSecrets = async (req: Request, res: Response) => {
environment,
workspaceId,
channel,
userAgent: req.headers?.['user-agent']
userAgent: req.headers?.['user-agent'],
isPaid
}
});
}
@@ -226,7 +231,8 @@ export const batchSecrets = async (req: Request, res: Response) => {
environment,
workspaceId,
channel,
userAgent: req.headers?.['user-agent']
userAgent: req.headers?.['user-agent'],
isPaid
}
});
}
@@ -261,7 +267,8 @@ export const batchSecrets = async (req: Request, res: Response) => {
environment,
workspaceId,
channel: channel,
userAgent: req.headers?.['user-agent']
userAgent: req.headers?.['user-agent'],
isPaid
}
});
}
@@ -376,6 +383,12 @@ export const createSecrets = async (req: Request, res: Response) => {
}
}
const workspace = await Workspace.findById(workspaceId);
if (!workspace) throw WorkspaceNotFoundError();
const orgPlan = await EELicenseService.getOrganizationPlan(workspace.organization.toString());
const isPaid = orgPlan.tier < 1;
let listOfSecretsToCreate;
if (Array.isArray(req.body.secrets)) {
// case: create multiple secrets
@@ -531,7 +544,8 @@ export const createSecrets = async (req: Request, res: Response) => {
environment,
workspaceId,
channel: channel,
userAgent: req.headers?.['user-agent']
userAgent: req.headers?.['user-agent'],
isPaid
}
});
}
@@ -595,6 +609,12 @@ export const getSecrets = async (req: Request, res: Response) => {
const normalizedPath = normalizePath(secretsPath as string)
const folders = await getFoldersInDirectory(workspaceId as string, environment as string, normalizedPath)
const workspace = await Workspace.findById(workspaceId);
if (!workspace) throw WorkspaceNotFoundError();
const orgPlan = await EELicenseService.getOrganizationPlan(workspace.organization.toString());
const isPaid = orgPlan.tier < 1;
// secrets to return
let secrets: ISecret[] = [];
@@ -727,7 +747,8 @@ export const getSecrets = async (req: Request, res: Response) => {
environment,
workspaceId,
channel,
userAgent: req.headers?.['user-agent']
userAgent: req.headers?.['user-agent'],
isPaid
}
});
}
@@ -938,6 +959,12 @@ export const updateSecrets = async (req: Request, res: Response) => {
workspaceId: new Types.ObjectId(key)
})
const workspace = await Workspace.findById(key);
if (!workspace) throw WorkspaceNotFoundError();
const orgPlan = await EELicenseService.getOrganizationPlan(workspace.organization.toString());
const isPaid = orgPlan.tier < 1;
const postHogClient = await TelemetryService.getPostHogClient();
if (postHogClient) {
postHogClient.capture({
@@ -950,7 +977,8 @@ export const updateSecrets = async (req: Request, res: Response) => {
environment: workspaceSecretObj[key][0].environment,
workspaceId: key,
channel: channel,
userAgent: req.headers?.['user-agent']
userAgent: req.headers?.['user-agent'],
isPaid
}
});
}
@@ -1072,6 +1100,14 @@ export const deleteSecrets = async (req: Request, res: Response) => {
workspaceId: new Types.ObjectId(key)
});
const organizationId = (
await Workspace.findOne({
_id: key
})
)?.organization?.toString();
const orgPlan = await EELicenseService.getOrganizationPlan(organizationId || '');
const isPaid = orgPlan.slug != 'starter';
const postHogClient = await TelemetryService.getPostHogClient();
if (postHogClient) {
postHogClient.capture({
@@ -1084,7 +1120,8 @@ export const deleteSecrets = async (req: Request, res: Response) => {
environment: workspaceSecretObj[key][0].environment,
workspaceId: key,
channel: channel,
userAgent: req.headers?.['user-agent']
userAgent: req.headers?.['user-agent'],
isPaid
}
});
}
+28 -3
View File
@@ -7,8 +7,9 @@ import {
} from '../../helpers/signup';
import { issueAuthTokens } from '../../helpers/auth';
import { INVITED, ACCEPTED } from '../../variables';
import request from '../../config/request';
import { standardRequest } from '../../config/request';
import { getLoopsApiKey, getHttpsEnabled } from '../../config';
import { updateSubscriptionOrgQuantity } from '../../helpers/organization';
/**
* Complete setting up user by adding their personal and auth information as part of the
@@ -87,6 +88,19 @@ export const completeAccountSignup = async (req: Request, res: Response) => {
user
});
// update organization membership statuses that are
// invited to completed with user attached
const membershipsToUpdate = await MembershipOrg.find({
inviteEmail: email,
status: INVITED
});
membershipsToUpdate.forEach(async (membership) => {
await updateSubscriptionOrgQuantity({
organizationId: membership.organization.toString()
});
});
// update organization membership statuses that are
// invited to completed with user attached
await MembershipOrg.updateMany(
@@ -109,7 +123,7 @@ export const completeAccountSignup = async (req: Request, res: Response) => {
// sending a welcome email to new users
if (await getLoopsApiKey()) {
await request.post("https://app.loops.so/api/v1/events/send", {
await standardRequest.post("https://app.loops.so/api/v1/events/send", {
"email": email,
"eventName": "Sign Up",
"firstName": firstName,
@@ -206,9 +220,20 @@ export const completeAccountInvite = async (req: Request, res: Response) => {
if (!user)
throw new Error('Failed to complete account for non-existent user');
// update organization membership statuses that are
// invited to completed with user attached
const membershipsToUpdate = await MembershipOrg.find({
inviteEmail: email,
status: INVITED
});
membershipsToUpdate.forEach(async (membership) => {
await updateSubscriptionOrgQuantity({
organizationId: membership.organization.toString()
});
});
await MembershipOrg.updateMany(
{
inviteEmail: email,