add stripe subscription id to org

This commit is contained in:
msukkari 2025-02-11 18:40:42 -08:00
parent 9665f149cd
commit 33ae585327
8 changed files with 15498 additions and 15122 deletions

29542
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Org" ADD COLUMN "subscriptionId" TEXT;

View file

@ -115,6 +115,8 @@ model Org {
repos Repo[] repos Repo[]
secrets Secret[] secrets Secret[]
subscriptionId String?
/// List of pending invites to this organization /// List of pending invites to this organization
invites Invite[] invites Invite[]
} }

View file

@ -1,7 +1,6 @@
'use server'; 'use server';
import Ajv from "ajv"; import Ajv from "ajv";
import { Stripe } from "stripe";
import { auth, getCurrentUserOrg } from "./auth"; import { auth, getCurrentUserOrg } from "./auth";
import { notAuthenticated, notFound, ServiceError, unexpectedError, orgDomainExists } from "@/lib/serviceError"; import { notAuthenticated, notFound, ServiceError, unexpectedError, orgDomainExists } from "@/lib/serviceError";
import { prisma } from "@/prisma"; import { prisma } from "@/prisma";
@ -99,7 +98,7 @@ export const checkIfOrgDomainExists = async (domain: string): Promise<boolean> =
return !!org; return !!org;
} }
export const createOrg = async (name: string, domain: string): Promise<{ id: number } | ServiceError> => { export const createOrg = async (name: string, domain: string, subscriptionId?: string): Promise<{ id: number } | ServiceError> => {
const session = await auth(); const session = await auth();
if (!session) { if (!session) {
return notAuthenticated(); return notAuthenticated();
@ -120,6 +119,7 @@ export const createOrg = async (name: string, domain: string): Promise<{ id: num
data: { data: {
name, name,
domain, domain,
subscriptionId,
members: { members: {
create: { create: {
userId: session.user.id, userId: session.user.id,

View file

@ -30,21 +30,27 @@ export default async function OnboardComplete({ searchParams }: OnboardCompleteP
} }
if (!sessionId || !orgName || !orgDomain) { if (!sessionId || !orgName || !orgDomain) {
console.error("Missing required parameters");
return <ErrorPage />; return <ErrorPage />;
} }
const stripeSession = await fetchStripeSession(sessionId); const stripeSession = await fetchStripeSession(sessionId);
if(stripeSession.payment_status !== "paid") { const stripeSubscription = stripeSession.subscription;
if(stripeSession.payment_status !== "paid" || !stripeSubscription) {
console.error("Invalid stripe session");
return <ErrorPage />; return <ErrorPage />;
} }
const res = await createOrg(orgName, orgDomain); const subscriptionId = stripeSubscription as string;
const res = await createOrg(orgName, orgDomain, subscriptionId);
if (isServiceError(res)) { if (isServiceError(res)) {
console.error("Failed to create org");
return <ErrorPage />; return <ErrorPage />;
} }
const orgSwitchRes = await switchActiveOrg(res.id); const orgSwitchRes = await switchActiveOrg(res.id);
if (isServiceError(orgSwitchRes)) { if (isServiceError(orgSwitchRes)) {
console.error("Failed to switch active org");
return <ErrorPage />; return <ErrorPage />;
} }

View file

@ -19,7 +19,9 @@ const onboardingFormSchema = z.object({
.max(30, { message: "Organization name must be at most 30 characters long." }), .max(30, { message: "Organization name must be at most 30 characters long." }),
domain: z.string() domain: z.string()
.min(2, { message: "Organization domain must be at least 3 characters long." }) .min(2, { message: "Organization domain must be at least 3 characters long." })
.max(20, { message: "Organization domain must be at most 20 characters long." }), .max(20, { message: "Organization domain must be at most 20 characters long." })
.regex(/^[a-zA-Z-]+$/, { message: "Organization domain must contain only letters and hyphens." })
.regex(/^[^-].*[^-]$/, { message: "Organization domain must not start or end with a hyphen." }),
}) })
export type OnboardingFormValues = z.infer<typeof onboardingFormSchema> export type OnboardingFormValues = z.infer<typeof onboardingFormSchema>

View file

@ -61,10 +61,11 @@ export function TrialCard({ orgCreateInfo }: { orgCreateInfo: OnboardingFormValu
<CardContent className="pt-2"> <CardContent className="pt-2">
<ul className="space-y-4 mb-6"> <ul className="space-y-4 mb-6">
{[ {[
"Index hundreds of repos from multiple code hosts (GitHub, GitLab, Gerrit, Gitea, etc.)",
"Powerful regex and symbol search",
"Blazingly fast code search", "Blazingly fast code search",
"Index hundreds of repos from multiple code hosts (GitHub, GitLab, Gerrit, Gitea, etc.). Self-hosted code sources supported.",
"Public and private repos supported.",
"Create sharable links to code snippets.", "Create sharable links to code snippets.",
"Powerful regex and symbol search",
].map((feature, index) => ( ].map((feature, index) => (
<li key={index} className="flex items-center"> <li key={index} className="flex items-center">
<div className="mr-3 flex-shrink-0"> <div className="mr-3 flex-shrink-0">

1051
yarn.lock

File diff suppressed because it is too large Load diff