feat: remove try-catch blocks for handling errors in middleware

This commit is contained in:
Spelchure
2023-05-01 17:14:39 +03:00
parent addac63700
commit 21eb1815c4
22 changed files with 2141 additions and 2580 deletions
+197 -207
View File
@@ -1,39 +1,34 @@
import * as Sentry from '@sentry/node';
import Stripe from 'stripe';
import { Types } from 'mongoose';
import Stripe from "stripe";
import { Types } from "mongoose";
import {
IUser,
User,
IServiceAccount,
ServiceAccount,
IServiceTokenData,
ServiceTokenData
} from '../models';
import { Organization, MembershipOrg } from '../models';
import {
ACCEPTED,
AUTH_MODE_JWT,
AUTH_MODE_SERVICE_ACCOUNT,
AUTH_MODE_SERVICE_TOKEN,
AUTH_MODE_API_KEY,
OWNER
} from '../variables';
import {
getStripeSecretKey,
getStripeProductPro,
getStripeProductTeam,
getStripeProductStarter
} from '../config';
IUser,
User,
IServiceAccount,
ServiceAccount,
IServiceTokenData,
ServiceTokenData,
} from "../models";
import { Organization, MembershipOrg } from "../models";
import {
UnauthorizedRequestError,
OrganizationNotFoundError
} from '../utils/errors';
ACCEPTED,
AUTH_MODE_JWT,
AUTH_MODE_SERVICE_ACCOUNT,
AUTH_MODE_SERVICE_TOKEN,
AUTH_MODE_API_KEY,
OWNER,
} from "../variables";
import {
validateUserClientForOrganization
} from '../helpers/user';
getStripeSecretKey,
getStripeProductPro,
getStripeProductTeam,
getStripeProductStarter,
} from "../config";
import {
validateServiceAccountClientForOrganization
} from '../helpers/serviceAccount';
UnauthorizedRequestError,
OrganizationNotFoundError,
} from "../utils/errors";
import { validateUserClientForOrganization } from "../helpers/user";
import { validateServiceAccountClientForOrganization } from "../helpers/serviceAccount";
/**
* Validate accepted clients for organization with id [organizationId]
@@ -42,69 +37,80 @@ import {
* @param {Types.ObjectId} obj.organizationId - id of organization to validate against
*/
const validateClientForOrganization = async ({
authData,
organizationId,
acceptedRoles,
acceptedStatuses
authData,
organizationId,
acceptedRoles,
acceptedStatuses,
}: {
authData: {
authMode: string;
authPayload: IUser | IServiceAccount | IServiceTokenData;
},
organizationId: Types.ObjectId;
acceptedRoles: Array<'owner' | 'admin' | 'member'>;
acceptedStatuses: Array<'invited' | 'accepted'>;
authData: {
authMode: string;
authPayload: IUser | IServiceAccount | IServiceTokenData;
};
organizationId: Types.ObjectId;
acceptedRoles: Array<"owner" | "admin" | "member">;
acceptedStatuses: Array<"invited" | "accepted">;
}) => {
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: 'Failed to find organization'
});
}
if (authData.authMode === AUTH_MODE_JWT && authData.authPayload instanceof User) {
const membershipOrg = await validateUserClientForOrganization({
user: authData.authPayload,
organization,
acceptedRoles,
acceptedStatuses
});
return ({ organization, membershipOrg });
}
const organization = await Organization.findById(organizationId);
if (authData.authMode === AUTH_MODE_SERVICE_ACCOUNT && authData.authPayload instanceof ServiceAccount) {
await validateServiceAccountClientForOrganization({
serviceAccount: authData.authPayload,
organization
});
return ({ organization });
}
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization",
});
}
if (authData.authMode === AUTH_MODE_SERVICE_TOKEN && authData.authPayload instanceof ServiceTokenData) {
throw UnauthorizedRequestError({
message: 'Failed service token authorization for organization'
});
}
if (
authData.authMode === AUTH_MODE_JWT &&
authData.authPayload instanceof User
) {
const membershipOrg = await validateUserClientForOrganization({
user: authData.authPayload,
organization,
acceptedRoles,
acceptedStatuses,
});
if (authData.authMode === AUTH_MODE_API_KEY && authData.authPayload instanceof User) {
const membershipOrg = await validateUserClientForOrganization({
user: authData.authPayload,
organization,
acceptedRoles,
acceptedStatuses
});
return ({ organization, membershipOrg });
}
throw UnauthorizedRequestError({
message: 'Failed client authorization for organization'
});
}
return { organization, membershipOrg };
}
if (
authData.authMode === AUTH_MODE_SERVICE_ACCOUNT &&
authData.authPayload instanceof ServiceAccount
) {
await validateServiceAccountClientForOrganization({
serviceAccount: authData.authPayload,
organization,
});
return { organization };
}
if (
authData.authMode === AUTH_MODE_SERVICE_TOKEN &&
authData.authPayload instanceof ServiceTokenData
) {
throw UnauthorizedRequestError({
message: "Failed service token authorization for organization",
});
}
if (
authData.authMode === AUTH_MODE_API_KEY &&
authData.authPayload instanceof User
) {
const membershipOrg = await validateUserClientForOrganization({
user: authData.authPayload,
organization,
acceptedRoles,
acceptedStatuses,
});
return { organization, membershipOrg };
}
throw UnauthorizedRequestError({
message: "Failed client authorization for organization",
});
};
/**
* Create an organization with name [name]
@@ -114,43 +120,37 @@ const validateClientForOrganization = async ({
* @param {Object} organization - new organization
*/
const createOrganization = async ({
name,
email
name,
email,
}: {
name: string;
email: string;
name: string;
email: string;
}) => {
let organization;
try {
// register stripe account
const stripe = new Stripe(await getStripeSecretKey(), {
apiVersion: '2022-08-01'
});
let organization;
// register stripe account
const stripe = new Stripe(await getStripeSecretKey(), {
apiVersion: "2022-08-01",
});
if (await getStripeSecretKey()) {
const customer = await stripe.customers.create({
email,
description: name
});
if (await getStripeSecretKey()) {
const customer = await stripe.customers.create({
email,
description: name,
});
organization = await new Organization({
name,
customerId: customer.id
}).save();
} else {
organization = await new Organization({
name
}).save();
}
organization = await new Organization({
name,
customerId: customer.id,
}).save();
} else {
organization = await new Organization({
name,
}).save();
}
await initSubscriptionOrg({ organizationId: organization._id });
} catch (err) {
Sentry.setUser({ email });
Sentry.captureException(err);
throw new Error(`Failed to create organization [err=${err}]`);
}
await initSubscriptionOrg({ organizationId: organization._id });
return organization;
return organization;
};
/**
@@ -162,57 +162,52 @@ const createOrganization = async ({
* @return {Subscription} obj.subscription - new subscription
*/
const initSubscriptionOrg = async ({
organizationId
organizationId,
}: {
organizationId: Types.ObjectId;
organizationId: Types.ObjectId;
}) => {
let stripeSubscription;
let subscription;
try {
// find organization
const organization = await Organization.findOne({
_id: organizationId
});
let stripeSubscription;
let subscription;
if (organization) {
if (organization.customerId) {
// initialize starter subscription with quantity of 0
const stripe = new Stripe(await getStripeSecretKey(), {
apiVersion: '2022-08-01'
});
// find organization
const organization = await Organization.findOne({
_id: organizationId,
});
const productToPriceMap = {
starter: await getStripeProductStarter(),
team: await getStripeProductTeam(),
pro: await getStripeProductPro()
};
if (organization) {
if (organization.customerId) {
// initialize starter subscription with quantity of 0
const stripe = new Stripe(await getStripeSecretKey(), {
apiVersion: "2022-08-01",
});
stripeSubscription = await stripe.subscriptions.create({
customer: organization.customerId,
items: [
{
price: productToPriceMap['starter'],
quantity: 1
}
],
payment_behavior: 'default_incomplete',
proration_behavior: 'none',
expand: ['latest_invoice.payment_intent']
});
}
} else {
throw new Error('Failed to initialize free organization subscription');
}
} catch (err) {
Sentry.setUser(null);
Sentry.captureException(err);
throw new Error('Failed to initialize free organization subscription');
}
const productToPriceMap = {
starter: await getStripeProductStarter(),
team: await getStripeProductTeam(),
pro: await getStripeProductPro(),
};
return {
stripeSubscription,
subscription
};
stripeSubscription = await stripe.subscriptions.create({
customer: organization.customerId,
items: [
{
price: productToPriceMap["starter"],
quantity: 1,
},
],
payment_behavior: "default_incomplete",
proration_behavior: "none",
expand: ["latest_invoice.payment_intent"],
});
}
} else {
throw new Error("Failed to initialize free organization subscription");
}
return {
stripeSubscription,
subscription,
};
};
/**
@@ -222,54 +217,49 @@ const initSubscriptionOrg = async ({
* @param {Number} obj.organizationId - id of subscription's organization
*/
const updateSubscriptionOrgQuantity = async ({
organizationId
organizationId,
}: {
organizationId: string;
organizationId: string;
}) => {
let stripeSubscription;
try {
// find organization
const organization = await Organization.findOne({
_id: organizationId
});
let stripeSubscription;
// find organization
const organization = await Organization.findOne({
_id: organizationId,
});
if (organization && organization.customerId) {
const quantity = await MembershipOrg.countDocuments({
organization: organizationId,
status: ACCEPTED
});
if (organization && organization.customerId) {
const quantity = await MembershipOrg.countDocuments({
organization: organizationId,
status: ACCEPTED,
});
const stripe = new Stripe(await getStripeSecretKey(), {
apiVersion: '2022-08-01'
});
const stripe = new Stripe(await getStripeSecretKey(), {
apiVersion: "2022-08-01",
});
const subscription = (
await stripe.subscriptions.list({
customer: organization.customerId
})
).data[0];
const subscription = (
await stripe.subscriptions.list({
customer: organization.customerId,
})
).data[0];
stripeSubscription = await stripe.subscriptions.update(subscription.id, {
items: [
{
id: subscription.items.data[0].id,
price: subscription.items.data[0].price.id,
quantity
}
]
});
}
} catch (err) {
Sentry.setUser(null);
Sentry.captureException(err);
}
stripeSubscription = await stripe.subscriptions.update(subscription.id, {
items: [
{
id: subscription.items.data[0].id,
price: subscription.items.data[0].price.id,
quantity,
},
],
});
}
return stripeSubscription;
return stripeSubscription;
};
export {
validateClientForOrganization,
createOrganization,
initSubscriptionOrg,
updateSubscriptionOrgQuantity
};
validateClientForOrganization,
createOrganization,
initSubscriptionOrg,
updateSubscriptionOrgQuantity,
};