Compare commits
4 Commits
cloud/novu
...
fix/openap
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eafe4d0cd8 | ||
|
|
50382e9186 | ||
|
|
00be5fb058 | ||
|
|
fc65f53e0c |
@@ -35,7 +35,10 @@ services:
|
|||||||
- SMTP_PASSWORD=${SMTP_PASSWORD}
|
- SMTP_PASSWORD=${SMTP_PASSWORD}
|
||||||
- SMTP_SECURE=${SMTP_SECURE}
|
- SMTP_SECURE=${SMTP_SECURE}
|
||||||
- EMAIL_FROM=${EMAIL_FROM}
|
- EMAIL_FROM=${EMAIL_FROM}
|
||||||
|
|
||||||
|
# Notifications
|
||||||
- NOVU_API_KEY=${NOVU_API_KEY}
|
- NOVU_API_KEY=${NOVU_API_KEY}
|
||||||
|
- DISCORD_WEBHOOK_URL=${DISCORD_WEBHOOK_URL}
|
||||||
|
|
||||||
# S3 storage
|
# S3 storage
|
||||||
- S3_ACCESS_KEY_ID=${S3_ACCESS_KEY_ID}
|
- S3_ACCESS_KEY_ID=${S3_ACCESS_KEY_ID}
|
||||||
|
|||||||
@@ -476,7 +476,7 @@ export const memberRouter = createTRPCRouter({
|
|||||||
openapi: {
|
openapi: {
|
||||||
summary: "Get invite information by code",
|
summary: "Get invite information by code",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
path: "/workspaces/{workspacePublicId}/invites/{inviteCode}",
|
path: "/invites/{inviteCode}",
|
||||||
description: "Get invite information by invite code",
|
description: "Get invite information by invite code",
|
||||||
tags: ["Invites"],
|
tags: ["Invites"],
|
||||||
protect: false,
|
protect: false,
|
||||||
@@ -521,7 +521,7 @@ export const memberRouter = createTRPCRouter({
|
|||||||
openapi: {
|
openapi: {
|
||||||
summary: "Accept an invite link",
|
summary: "Accept an invite link",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
path: "/workspaces/{workspacePublicId}/invites/accept",
|
path: "/invites/accept",
|
||||||
description: "Accepts an invitation via invite link",
|
description: "Accepts an invitation via invite link",
|
||||||
tags: ["Invites"],
|
tags: ["Invites"],
|
||||||
protect: false,
|
protect: false,
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
import type { Subscription } from "@better-auth/stripe";
|
||||||
|
import type Stripe from "stripe";
|
||||||
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
||||||
import { stripe } from "@better-auth/stripe";
|
import { stripe } from "@better-auth/stripe";
|
||||||
|
import { ChatOrPushProviderEnum } from "@novu/api/models/components";
|
||||||
import { betterAuth } from "better-auth";
|
import { betterAuth } from "better-auth";
|
||||||
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
||||||
import { createAuthEndpoint, createAuthMiddleware } from "better-auth/api";
|
import { createAuthEndpoint, createAuthMiddleware } from "better-auth/api";
|
||||||
@@ -178,19 +181,17 @@ export const initAuth = (db: dbClient) => {
|
|||||||
freeTrial: {
|
freeTrial: {
|
||||||
days: 14,
|
days: 14,
|
||||||
onTrialStart: async (subscription) => {
|
onTrialStart: async (subscription) => {
|
||||||
// Called when a trial starts
|
await triggerWorkflow(db, "trial-start", subscription);
|
||||||
// @todo: send trial start email
|
|
||||||
// await sendTrialStartEmail(subscription.referenceId);
|
|
||||||
},
|
},
|
||||||
onTrialEnd: async ({ subscription }, request) => {
|
onTrialEnd: async ({ subscription }) => {
|
||||||
// Called when a trial ends
|
await triggerWorkflow(db, "trial-end", subscription);
|
||||||
// @todo: send trial end email
|
|
||||||
// await sendTrialEndEmail(user.email);
|
|
||||||
},
|
},
|
||||||
onTrialExpired: async (subscription) => {
|
onTrialExpired: async (subscription) => {
|
||||||
// Called when a trial expires without conversion
|
await triggerWorkflow(
|
||||||
// @todo: send trial expired email
|
db,
|
||||||
// await sendTrialExpiredEmail(subscription.referenceId);
|
"trial-expired",
|
||||||
|
subscription,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -202,19 +203,17 @@ export const initAuth = (db: dbClient) => {
|
|||||||
freeTrial: {
|
freeTrial: {
|
||||||
days: 14,
|
days: 14,
|
||||||
onTrialStart: async (subscription) => {
|
onTrialStart: async (subscription) => {
|
||||||
// Called when a trial starts
|
await triggerWorkflow(db, "trial-start", subscription);
|
||||||
// @todo: send trial start email
|
|
||||||
// await sendTrialStartEmail(subscription.referenceId);
|
|
||||||
},
|
},
|
||||||
onTrialEnd: async ({ subscription }, request) => {
|
onTrialEnd: async ({ subscription }) => {
|
||||||
// Called when a trial ends
|
await triggerWorkflow(db, "trial-end", subscription);
|
||||||
// @todo: send trial end email
|
|
||||||
// await sendTrialEndEmail(user.email);
|
|
||||||
},
|
},
|
||||||
onTrialExpired: async (subscription) => {
|
onTrialExpired: async (subscription) => {
|
||||||
// Called when a trial expires without conversion
|
await triggerWorkflow(
|
||||||
// @todo: send trial expired email
|
db,
|
||||||
// await sendTrialExpiredEmail(subscription.referenceId);
|
"trial-expired",
|
||||||
|
subscription,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -418,6 +417,17 @@ export const initAuth = (db: dbClient) => {
|
|||||||
},
|
},
|
||||||
workflowId: "user-signup",
|
workflowId: "user-signup",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await notificationClient.subscribers.credentials.update(
|
||||||
|
{
|
||||||
|
providerId: ChatOrPushProviderEnum.Discord,
|
||||||
|
credentials: {
|
||||||
|
webhookUrl: process.env.DISCORD_WEBHOOK_URL!,
|
||||||
|
},
|
||||||
|
integrationIdentifier: "discord",
|
||||||
|
},
|
||||||
|
user.id,
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(
|
console.error(
|
||||||
"Error adding user to notification client",
|
"Error adding user to notification client",
|
||||||
@@ -462,3 +472,34 @@ export const initAuth = (db: dbClient) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async function triggerWorkflow(
|
||||||
|
db: dbClient,
|
||||||
|
workflowId: string,
|
||||||
|
subscription: Subscription,
|
||||||
|
cancellationDetails?: Stripe.Subscription.CancellationDetails | null,
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
if (!subscription.stripeCustomerId || !notificationClient) return;
|
||||||
|
|
||||||
|
const user = await userRepo.getByStripeCustomerId(
|
||||||
|
db,
|
||||||
|
subscription.stripeCustomerId,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!user || !notificationClient) return;
|
||||||
|
|
||||||
|
await notificationClient.trigger({
|
||||||
|
to: {
|
||||||
|
subscriberId: user.id,
|
||||||
|
},
|
||||||
|
payload: {
|
||||||
|
...subscription,
|
||||||
|
cancellationDetails,
|
||||||
|
},
|
||||||
|
workflowId,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error triggering workflow", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,6 +28,15 @@ export const getById = async (db: dbClient, userId: string) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getByStripeCustomerId = async (
|
||||||
|
db: dbClient,
|
||||||
|
stripeCustomerId: string,
|
||||||
|
) => {
|
||||||
|
return await db.query.users.findFirst({
|
||||||
|
where: eq(users.stripeCustomerId, stripeCustomerId),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const getByEmail = (db: dbClient, email: string) => {
|
export const getByEmail = (db: dbClient, email: string) => {
|
||||||
return db.query.users.findFirst({
|
return db.query.users.findFirst({
|
||||||
columns: {
|
columns: {
|
||||||
|
|||||||
@@ -71,4 +71,13 @@ export const updateSubscriptionSeats = async (
|
|||||||
return updatedSubscription;
|
return updatedSubscription;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getCancellationDetails = async (
|
||||||
|
stripeSubscriptionId: string,
|
||||||
|
): Promise<Stripe.Subscription.CancellationDetails | null> => {
|
||||||
|
const stripe = createStripeClient();
|
||||||
|
const stripeSubscription =
|
||||||
|
await stripe.subscriptions.retrieve(stripeSubscriptionId);
|
||||||
|
return stripeSubscription.cancellation_details ?? null;
|
||||||
|
};
|
||||||
|
|
||||||
export { createStripeClient };
|
export { createStripeClient };
|
||||||
|
|||||||
@@ -99,6 +99,7 @@
|
|||||||
"NEXT_PUBLIC_KAN_ENV",
|
"NEXT_PUBLIC_KAN_ENV",
|
||||||
"NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY",
|
"NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY",
|
||||||
"STRIPE_SECRET_KEY",
|
"STRIPE_SECRET_KEY",
|
||||||
|
"DISCORD_WEBHOOK_URL",
|
||||||
"STRIPE_WEBHOOK_SECRET",
|
"STRIPE_WEBHOOK_SECRET",
|
||||||
"STRIPE_WEBHOOK_SECRET_LEGACY",
|
"STRIPE_WEBHOOK_SECRET_LEGACY",
|
||||||
"STRIPE_PRO_PLAN_MONTHLY_PRICE_ID",
|
"STRIPE_PRO_PLAN_MONTHLY_PRICE_ID",
|
||||||
|
|||||||
Reference in New Issue
Block a user