diff --git a/.env.example b/.env.example index 8421637b3..d415e8039 100644 --- a/.env.example +++ b/.env.example @@ -19,6 +19,8 @@ SMTP_FROM_EMAIL_ADDRESS="flo@kula.app" SMTP_FROM_NAME="Flo Ho" # add your stripe API key here +NEXT_PUBLIC_STRIPE_ENABLED=false +STRIPE_ENABLED=false STRIPE_WEBHOOK_SECRET= STRIPE_SECRET_KEY= STRIPE_USE_AUTOMATIC_TAX= diff --git a/config/interfaces/Config.ts b/config/interfaces/Config.ts index d8ffaf0f7..ff73faa67 100644 --- a/config/interfaces/Config.ts +++ b/config/interfaces/Config.ts @@ -13,6 +13,7 @@ import { UsageReportConfig } from "./UsageReportConfig"; export interface Config { client: { sentryConfig: SentryConfig; + stripeConfig: StripeConfig; }; server: { database: DatabaseConfig; diff --git a/config/interfaces/StripeConfig.ts b/config/interfaces/StripeConfig.ts index 34380f548..44038c5f4 100644 --- a/config/interfaces/StripeConfig.ts +++ b/config/interfaces/StripeConfig.ts @@ -1,8 +1,9 @@ export interface StripeConfig { - apiVersion: string; - webhookSecret: string; - secretKey: string; - useAutomaticTax: boolean; + isEnabled: boolean; + apiVersion?: string; + webhookSecret?: string; + secretKey?: string; + useAutomaticTax?: boolean; dynamicTaxRates?: Array; taxRates?: Array; } diff --git a/config/loadConfig.ts b/config/loadConfig.ts index 8bd0e326a..a17527485 100644 --- a/config/loadConfig.ts +++ b/config/loadConfig.ts @@ -64,6 +64,12 @@ export function loadConfig(): Config { env.NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE ) ?? 0.2, }, + stripeConfig: { + isEnabled: + parseBooleanEnvValue(env.STRIPE_ENABLED) ?? + parseBooleanEnvValue(env.NEXT_PUBLIC_STRIPE_ENABLED) ?? + false, + }, }, server: { nextAuth: { @@ -107,6 +113,7 @@ export function loadConfig(): Config { sentinelPassword: env.REDIS_SENTINEL_PASSWORD, }, stripeConfig: { + isEnabled: parseBooleanEnvValue(env.STRIPE_ENABLED) ?? false, apiVersion: env.STRIPE_API_VERSION || "", webhookSecret: env.STRIPE_WEBHOOK_SECRET || "", secretKey: env.STRIPE_SECRET_KEY || "", diff --git a/pages/api/frontend/v0.1/stripe/checkoutSession.ts b/pages/api/frontend/v0.1/stripe/checkoutSession.ts index f7d73b9c1..d41c536c5 100644 --- a/pages/api/frontend/v0.1/stripe/checkoutSession.ts +++ b/pages/api/frontend/v0.1/stripe/checkoutSession.ts @@ -12,8 +12,15 @@ export default async function handler( req: NextApiRequest, res: NextApiResponse ) { - const stripeConfig = loadConfig().server.stripeConfig; const logger = new Logger(__filename); + const stripeConfig = loadConfig().server.stripeConfig; + + if (!stripeConfig.isEnabled) { + logger.error("stripe is disabled but endpoint has been called"); + return res + .status(StatusCodes.SERVICE_UNAVAILABLE) + .json({ message: "Endpoint is disabled" }); + } const userInOrg = await getUserWithRoleFromRequest(req, res); @@ -30,6 +37,9 @@ export default async function handler( switch (req.method) { case "POST": + if (!stripeConfig.secretKey) { + throw new Error("Stripe secret key is not configured"); + } const stripe = new Stripe(stripeConfig.secretKey, { apiVersion: "2023-08-16", }); @@ -44,11 +54,9 @@ export default async function handler( if (!org) { logger.error(`No organisation found with id ${userInOrg.orgId}`); - return res - .status(StatusCodes.NOT_FOUND) - .json({ - message: `No organisation found with id ${userInOrg.orgId}`, - }); + return res.status(StatusCodes.NOT_FOUND).json({ + message: `No organisation found with id ${userInOrg.orgId}`, + }); } if (!req.body.products || !Array.isArray(req.body.products)) { @@ -96,7 +104,7 @@ export default async function handler( let sessionOptions: Stripe.Checkout.SessionCreateParams = { allow_promotion_codes: true, automatic_tax: { - enabled: stripeConfig.useAutomaticTax, + enabled: !!stripeConfig.useAutomaticTax, }, billing_address_collection: "required", client_reference_id: req.body.orgId, diff --git a/pages/api/frontend/v0.1/stripe/customerPortal.ts b/pages/api/frontend/v0.1/stripe/customerPortal.ts index c7da8d56d..c68837f1c 100644 --- a/pages/api/frontend/v0.1/stripe/customerPortal.ts +++ b/pages/api/frontend/v0.1/stripe/customerPortal.ts @@ -14,6 +14,13 @@ export default async function handler( const config = loadConfig(); const logger = new Logger(__filename); + if (!config.server.stripeConfig.isEnabled) { + logger.error("stripe is disabled but endpoint has been called"); + return res + .status(StatusCodes.SERVICE_UNAVAILABLE) + .json({ message: "Endpoint is disabled" }); + } + const user = await getUserWithRoleFromRequest(req, res); if (!user) { @@ -31,7 +38,11 @@ export default async function handler( switch (req.method) { case "POST": - const stripe = new Stripe(process.env.STRIPE_SECRET_KEY || "", { + const stripeConfig = config.server.stripeConfig; + if (!stripeConfig.secretKey) { + throw new Error("Stripe secret key is not configured"); + } + const stripe = new Stripe(stripeConfig.secretKey, { apiVersion: "2023-08-16", }); diff --git a/pages/api/frontend/v0.1/stripe/products.ts b/pages/api/frontend/v0.1/stripe/products.ts index 1dd987f3b..acfde6da9 100644 --- a/pages/api/frontend/v0.1/stripe/products.ts +++ b/pages/api/frontend/v0.1/stripe/products.ts @@ -11,9 +11,15 @@ const logger = new Logger(__filename); export async function getProducts(): Promise { const config = loadConfig(); - const stripe = new Stripe(process.env.STRIPE_SECRET_KEY || "", { + + const stripeConfig = loadConfig().server.stripeConfig; + if (!stripeConfig.secretKey) { + throw new Error("Stripe secret key is not configured"); + } + const stripe = new Stripe(stripeConfig.secretKey, { apiVersion: "2023-08-16", }); + const freeProduct: Product = { id: "FREE", description: "For checking it out", @@ -150,6 +156,15 @@ export default async function handler( req: NextApiRequest, res: NextApiResponse ) { + const stripeConfig = loadConfig().server.stripeConfig; + + if (!stripeConfig.isEnabled) { + logger.error("stripe is disabled but endpoint has been called"); + return res + .status(StatusCodes.SERVICE_UNAVAILABLE) + .json({ message: "Endpoint is disabled" }); + } + switch (req.method) { case "GET": try { diff --git a/pages/api/frontend/v0.1/stripe/subscriptions/[orgId].ts b/pages/api/frontend/v0.1/stripe/subscriptions/[orgId].ts index 0465c5ece..c95df635f 100644 --- a/pages/api/frontend/v0.1/stripe/subscriptions/[orgId].ts +++ b/pages/api/frontend/v0.1/stripe/subscriptions/[orgId].ts @@ -1,5 +1,6 @@ import { StatusCodes } from "http-status-codes"; import type { NextApiRequest, NextApiResponse } from "next"; +import { loadConfig } from "../../../../../../config/loadConfig"; import prisma from "../../../../../../lib/services/db"; import { getUserWithRoleFromRequest } from "../../../../../../util/auth"; import { Logger } from "../../../../../../util/logger"; @@ -9,6 +10,14 @@ export default async function handler( res: NextApiResponse ) { const logger = new Logger(__filename); + const stripeConfig = loadConfig().server.stripeConfig; + + if (!stripeConfig.isEnabled) { + logger.error("stripe is disabled but endpoint has been called"); + return res + .status(StatusCodes.SERVICE_UNAVAILABLE) + .json({ message: "Endpoint is disabled" }); + } const userInOrg = await getUserWithRoleFromRequest(req, res); diff --git a/pages/api/usageReport.ts b/pages/api/usageReport.ts index 39acfc101..fc2ce99fc 100644 --- a/pages/api/usageReport.ts +++ b/pages/api/usageReport.ts @@ -8,8 +8,16 @@ export default async function handler( req: NextApiRequest, res: NextApiResponse ) { - const usageReportingConfig = loadConfig().server.usageReport; const logger = new Logger(__filename); + const usageReportingConfig = loadConfig().server.usageReport; + const stripeConfig = loadConfig().server.stripeConfig; + + if (!stripeConfig.isEnabled) { + logger.error("stripe is disabled but endpoint has been called"); + return res + .status(StatusCodes.SERVICE_UNAVAILABLE) + .json({ message: "Endpoint is disabled" }); + } if ( req.headers.authorization !== `Bearer ${usageReportingConfig.apiKey}` && diff --git a/pages/api/v0.1/messages.ts b/pages/api/v0.1/messages.ts index 58b5a9a4a..8721683e9 100644 --- a/pages/api/v0.1/messages.ts +++ b/pages/api/v0.1/messages.ts @@ -128,97 +128,99 @@ export default async function handler( } // Start of quota limitation - try { - const products = await getProducts(); + if (config.server.stripeConfig.isEnabled) { + try { + const products = await getProducts(); - // Check if there is a subItem with isMetered set to true - // Metered subItems do not have a limit - let hasMeteredSubItem = false; - // There should be 0 or 1 sub - let subFromDb = app?.organisation?.subs[0]; + // Check if there is a subItem with isMetered set to true + // Metered subItems do not have a limit + let hasMeteredSubItem = false; + // There should be 0 or 1 sub + let subFromDb = app?.organisation?.subs[0]; - if (app?.organisation?.subs) { - for (const sub of app.organisation.subs) { - if (sub.subItems?.some((subItem) => subItem.metered === true)) { - hasMeteredSubItem = true; - break; + if (app?.organisation?.subs) { + for (const sub of app.organisation.subs) { + if (sub.subItems?.some((subItem) => subItem.metered === true)) { + hasMeteredSubItem = true; + break; + } } } - } - // If not metered, check for the limit - if (!hasMeteredSubItem) { - let countingStartDate = new Date(); + // If not metered, check for the limit + if (!hasMeteredSubItem) { + let countingStartDate = new Date(); - // Free version counts back plainly one month - if (!subFromDb) { - countingStartDate.setMonth(countingStartDate.getMonth() - 1); - } else { - // use current period start of active subscription - countingStartDate = subFromDb.currentPeriodStart; - } + // Free version counts back plainly one month + if (!subFromDb) { + countingStartDate.setMonth(countingStartDate.getMonth() - 1); + } else { + // use current period start of active subscription + countingStartDate = subFromDb.currentPeriodStart; + } - // Prepare array of app ids of organisation - const appIds = app?.organisation?.apps?.map((app) => app.id) || []; + // Prepare array of app ids of organisation + const appIds = app?.organisation?.apps?.map((app) => app.id) || []; - // Count requests across all apps of the org - const requestCount = await prisma.loggedApiRequests.count({ - where: { - appId: { - in: appIds, - }, - createdAt: { - gte: countingStartDate, + // Count requests across all apps of the org + const requestCount = await prisma.loggedApiRequests.count({ + where: { + appId: { + in: appIds, + }, + createdAt: { + gte: countingStartDate, + }, }, - }, - }); - logger.log( - `Request count for org with id '${app.orgId}' is ${requestCount}` - ); - - let isLimitReached = false; - - // Check whether quota/limit for the request has been met (active subscription) - if (subFromDb) { - const targetProduct = products.find( - (product: { id: string | undefined }) => - product.id === subFromDb?.subItems[0].productId + }); + logger.log( + `Request count for org with id '${app.orgId}' is ${requestCount}` ); - if (!targetProduct) { - logger.error( - `No product found for org with id '${app.orgId}' and active sub with id '${subFromDb.subId}'` + let isLimitReached = false; + + // Check whether quota/limit for the request has been met (active subscription) + if (subFromDb) { + const targetProduct = products.find( + (product: { id: string | undefined }) => + product.id === subFromDb?.subItems[0].productId ); - return res - .status(StatusCodes.INTERNAL_SERVER_ERROR) - .json({ message: "Please try again later" }); - } - logger.log( - `Request limit for org with id '${app.orgId}' is ${targetProduct.requests}` - ); - if (requestCount >= Number(targetProduct.requests)) { + if (!targetProduct) { + logger.error( + `No product found for org with id '${app.orgId}' and active sub with id '${subFromDb.subId}'` + ); + return res + .status(StatusCodes.INTERNAL_SERVER_ERROR) + .json({ message: "Please try again later" }); + } + + logger.log( + `Request limit for org with id '${app.orgId}' is ${targetProduct.requests}` + ); + if (requestCount >= Number(targetProduct.requests)) { + isLimitReached = true; + } + } else if (!subFromDb && requestCount >= FREE_SUB_REQUEST_LIMIT) { + // Check quota/limit for free version isLimitReached = true; } - } else if (!subFromDb && requestCount >= FREE_SUB_REQUEST_LIMIT) { - // Check quota/limit for free version - isLimitReached = true; - } - // Return error if limit has been reached and the request cannot be served - if (isLimitReached) { - logger.log( - `The limit has been currently reached for org with id '${app?.orgId}'` - ); - return res.status(StatusCodes.PAYMENT_REQUIRED).json({ - message: "The limit for the current abo has been reached.", - }); + // Return error if limit has been reached and the request cannot be served + if (isLimitReached) { + logger.log( + `The limit has been currently reached for org with id '${app?.orgId}'` + ); + return res.status(StatusCodes.PAYMENT_REQUIRED).json({ + message: "The limit for the current abo has been reached.", + }); + } } + } catch (error: any) { + return res + .status(StatusCodes.INTERNAL_SERVER_ERROR) + .json({ message: error.message }); } - } catch (error: any) { - return res - .status(StatusCodes.INTERNAL_SERVER_ERROR) - .json({ message: error.message }); } logger.log(`Looking up all messages for app with id '${app.id}'`); diff --git a/pages/api/webhooks/stripe.ts b/pages/api/webhooks/stripe.ts index e3edf8aa4..fb2d8dda7 100644 --- a/pages/api/webhooks/stripe.ts +++ b/pages/api/webhooks/stripe.ts @@ -27,10 +27,20 @@ export default async function handler( const logger = new Logger(__filename); const stripeConfig = loadConfig().server.stripeConfig; + if (!stripeConfig.secretKey) { + throw new Error("Stripe secret key is not configured"); + } const stripe = new Stripe(stripeConfig.secretKey, { apiVersion: "2023-08-16", }); + if (!stripeConfig.isEnabled) { + logger.error("stripe is disabled but endpoint has been called"); + return res + .status(StatusCodes.SERVICE_UNAVAILABLE) + .json({ message: "Endpoint is disabled" }); + } + switch (req.method) { case "POST": const buf = await buffer(req); diff --git a/pages/dashboard.tsx b/pages/dashboard.tsx index 4e59a2677..1f3b3d409 100644 --- a/pages/dashboard.tsx +++ b/pages/dashboard.tsx @@ -1,44 +1,42 @@ -import { useRouter } from "next/router"; -import { useEffect, useState } from "react"; -import styles from "../styles/Home.module.css"; -import { getSession } from "next-auth/react"; -import getDirectInviteToken from "../api/tokens/getDirectInviteToken"; -import getOrgInviteToken from "../api/tokens/getOrgInviteToken"; -import joinOrgViaDirectInvite from "../api/tokens/joinOrgViaDirectInvite"; -import joinOrgViaOrgInvite from "../api/tokens/joinOrgViaOrgInvite"; -import { useOrgs } from "../api/orgs/useOrgs"; -import Routes from "../routes/routes"; -import { OrgInvite } from "../models/orgInvite"; import { - Button, - Table, - Thead, - Th, - Tr, - Td, - Tbody, AlertDialog, AlertDialogBody, + AlertDialogCloseButton, + AlertDialogContent, AlertDialogFooter, AlertDialogHeader, - AlertDialogContent, AlertDialogOverlay, - AlertDialogCloseButton, - useToast, - useDisclosure, + Button, + Heading, Skeleton, Stack, - Heading, + Table, Tag, + Tbody, + Td, + Th, + Thead, + Tr, + useDisclosure, + useToast, } from "@chakra-ui/react"; -import React from "react"; -import { - getColorLabel, - translateSubName, -} from "../util/nameTag"; +import { getSession } from "next-auth/react"; +import { useRouter } from "next/router"; +import React, { useEffect, useState } from "react"; +import { useOrgs } from "../api/orgs/useOrgs"; +import getDirectInviteToken from "../api/tokens/getDirectInviteToken"; +import getOrgInviteToken from "../api/tokens/getOrgInviteToken"; +import joinOrgViaDirectInvite from "../api/tokens/joinOrgViaDirectInvite"; +import joinOrgViaOrgInvite from "../api/tokens/joinOrgViaOrgInvite"; +import { loadConfig } from "../config/loadConfig"; +import { OrgInvite } from "../models/orgInvite"; +import Routes from "../routes/routes"; +import styles from "../styles/Home.module.css"; +import { getColorLabel, translateSubName } from "../util/nameTag"; export default function DashboardPage() { const router = useRouter(); + const stripeConfig = loadConfig().client.stripeConfig; const { invite, directinvite } = router.query; @@ -159,16 +157,18 @@ export default function DashboardPage() { {org.id} {org.name} - - {translateSubName(org?.subName)} - + {stripeConfig.isEnabled && ( + + {translateSubName(org?.subName)} + + )} ); diff --git a/pages/orgs/[orgId]/settings.tsx b/pages/orgs/[orgId]/settings.tsx index 6a014c4ea..6651a8abf 100644 --- a/pages/orgs/[orgId]/settings.tsx +++ b/pages/orgs/[orgId]/settings.tsx @@ -45,6 +45,7 @@ import { useUsers } from "../../../api/orgs/useUsers"; import createCustomerPortalSession from "../../../api/stripe/createCustomerPortalSession"; import getSubscriptions from "../../../api/stripe/getSubscriptions"; import resetOrgInvitationToken from "../../../api/tokens/resetOrgInvitationToken"; +import { loadConfig } from "../../../config/loadConfig"; import { Org } from "../../../models/org"; import { Subscription } from "../../../models/subscription"; import Routes from "../../../routes/routes"; @@ -54,6 +55,7 @@ import { getColorLabel, translateSubName } from "../../../util/nameTag"; export default function EditOrgPage() { const router = useRouter(); const toast = useToast(); + const stripeConfig = loadConfig().client.stripeConfig; const { isOpen, onOpen, onClose } = useDisclosure(); const cancelRef = React.useRef(null); @@ -112,8 +114,10 @@ export default function EditOrgPage() { setLoading(false); }; - fetchUserSubscriptions(); - }, [router.isReady, orgId, toast]); + if (stripeConfig.isEnabled) { + fetchUserSubscriptions(); + } + }, [router.isReady, orgId, toast, stripeConfig.isEnabled]); const { data: session } = useSession(); @@ -547,103 +551,108 @@ export default function EditOrgPage() { {users?.length == 0 &&

no data to show

} {userRole === "ADMIN" && ( <> - - Your subscription - - {!loading && subs?.length != 0 && ( -
- - - - - - - - - - - {subs?.map((sub, index) => { - return ( - - - - - - ); - })} - -
- Org Id - - Organisation - - Subscription -
{sub.org.id}{sub.org.name} - - {translateSubName(sub.subName)} - -
- -
- -
- {loading && ( + {stripeConfig.isEnabled && ( + <> + + Your subscription + + {!loading && subs?.length != 0 && (
- loading ... - + + + + + + + + + + + {subs?.map((sub, index) => { + return ( + + + + + + ); + })} + +
+ Org Id + + Organisation + + Subscription +
{sub.org.id}{sub.org.name} + + {translateSubName(sub.subName)} + +
+ +
+ +
+ {loading && ( +
+ + loading ... + + +
+ )}
)} -
- )} - {!loading && subs?.length == 0 && ( -
- currently no active subscription -
- )} - {!loading && subs?.length == 0 && ( -
- -
- )} - {!loading && subs?.length == 0 && isCustomer && ( -
- -
+ {!loading && subs?.length == 0 && ( +
+ currently no active subscription +
+ )} + {!loading && subs?.length == 0 && ( +
+ +
+ )} + {!loading && subs?.length == 0 && isCustomer && ( +
+ +
+ )} + )} -
Delete Organisation diff --git a/pages/orgs/[orgId]/upgrade.tsx b/pages/orgs/[orgId]/upgrade.tsx index 97ff18aeb..9ec93f86c 100644 --- a/pages/orgs/[orgId]/upgrade.tsx +++ b/pages/orgs/[orgId]/upgrade.tsx @@ -3,16 +3,33 @@ import { useRouter } from "next/router"; import styles from "../../../styles/Home.module.css"; import { Heading, Skeleton, useToast } from "@chakra-ui/react"; +import { useEffect } from "react"; import { useProducts } from "../../../api/stripe/useProducts"; import ProductCard from "../../../components/ProductCard"; +import { loadConfig } from "../../../config/loadConfig"; +import Routes from "../../../routes/routes"; export default function EditOrgPage() { const router = useRouter(); const toast = useToast(); - const { products, isError, isLoading } = useProducts(); + const stripeConfig = loadConfig().client.stripeConfig; const orgId = Number(router.query.orgId); + useEffect(() => { + if (!router.isReady) return; + + function navigateToDashboardPage() { + router.push(Routes.DASHBOARD); + } + + if (!stripeConfig.isEnabled) { + navigateToDashboardPage(); + } + }, [router.isReady, router, stripeConfig.isEnabled]); + + const { products, isError, isLoading } = useProducts(); + if (isError) { toast({ title: "Error!", diff --git a/pages/orgs/new.tsx b/pages/orgs/new.tsx index 3fbb3eb38..9ea2ced8a 100644 --- a/pages/orgs/new.tsx +++ b/pages/orgs/new.tsx @@ -1,21 +1,23 @@ -import { FormEvent, useState } from "react"; -import styles from "../../styles/Home.module.css"; -import { getSession } from "next-auth/react"; import { - Input, - useToast, - Heading, + Button, FormControl, FormLabel, - Button, + Heading, + Input, + useToast, } from "@chakra-ui/react"; +import { getSession } from "next-auth/react"; +import { useRouter } from "next/router"; +import { FormEvent, useState } from "react"; import createOrg from "../../api/orgs/createOrg"; +import { loadConfig } from "../../config/loadConfig"; import Routes from "../../routes/routes"; -import { useRouter } from "next/router"; +import styles from "../../styles/Home.module.css"; export default function NewOrgPage() { const router = useRouter(); const toast = useToast(); + const stripeConfig = loadConfig().client.stripeConfig; const [orgName, setOrgName] = useState(""); @@ -24,10 +26,10 @@ export default function NewOrgPage() { try { const org = await createOrg(orgName); - + toast({ title: "Success!", - description: 'New organisation created.', + description: "New organisation created.", status: "success", isClosable: true, duration: 6000, @@ -35,7 +37,11 @@ export default function NewOrgPage() { resetForm(); - navigateToUpgradePage(org.orgId); + if (stripeConfig.isEnabled) { + navigateToUpgradePage(org.orgId); + } else { + navigateToOrgAppsPage(org.orgId); + } } catch (error) { toast({ title: "Error while creating new organisation!", @@ -46,11 +52,15 @@ export default function NewOrgPage() { }); } } - + function navigateToUpgradePage(orgId: number) { router.push(Routes.getOrgUpgradeByOrgId(orgId)); } + function navigateToOrgAppsPage(orgId: number) { + router.push(Routes.getOrgAppsByOrgId(orgId)); + } + function resetForm() { (document.getElementById("orgForm") as HTMLFormElement)?.reset(); } @@ -59,24 +69,24 @@ export default function NewOrgPage() { <>
-
- New Organisation -
- -
- Name - setOrgName(event.target.value)} - /> -
- -
-
-
+
+ New Organisation +
+ +
+ Name + setOrgName(event.target.value)} + /> +
+ +
+
+
diff --git a/pages/subscription.tsx b/pages/subscription.tsx index f1a31ce44..a0e198dd6 100644 --- a/pages/subscription.tsx +++ b/pages/subscription.tsx @@ -2,17 +2,31 @@ import { Button, Heading, Spinner, Stack, useToast } from "@chakra-ui/react"; import { getSession } from "next-auth/react"; import { useRouter } from "next/router"; import { useEffect, useState } from "react"; +import { loadConfig } from "../config/loadConfig"; import Routes from "../routes/routes"; import styles from "../styles/Home.module.css"; export default function ProfilePage() { const router = useRouter(); const toast = useToast(); + const stripeConfig = loadConfig().client.stripeConfig; const [loading, setLoading] = useState(true); let { success, canceled, orgId } = router.query; + useEffect(() => { + if (!router.isReady) return; + + function navigateToDashboardPage() { + router.push(Routes.DASHBOARD); + } + + if (!stripeConfig.isEnabled) { + navigateToDashboardPage(); + } + }, [router.isReady, router, stripeConfig.isEnabled]); + function navigateToDashboardPage() { router.push(Routes.DASHBOARD); } diff --git a/util/stripe/reportUsage.ts b/util/stripe/reportUsage.ts index 94463a6f2..7dac3ba08 100644 --- a/util/stripe/reportUsage.ts +++ b/util/stripe/reportUsage.ts @@ -1,10 +1,15 @@ import Stripe from "stripe"; +import { loadConfig } from "../../config/loadConfig"; import prisma from "../../lib/services/db"; import { Product } from "../../models/product"; import { getProducts } from "../../pages/api/frontend/v0.1/stripe/products"; import { Logger } from "../logger"; -const stripe = new Stripe(process.env.STRIPE_SECRET_KEY || "", { +const stripeConfig = loadConfig().server.stripeConfig; +if (!stripeConfig.secretKey) { + throw new Error("Stripe secret key is not configured"); +} +const stripe = new Stripe(stripeConfig.secretKey, { apiVersion: "2023-08-16", });