diff --git a/package.json b/package.json index 69da4cdf..f60d52e5 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "db:sqlite:generate": "drizzle-kit generate --config=./drizzle.sqlite.config.ts", "db:pg:push": "npx tsx server/db/pg/migrate.ts", "db:sqlite:push": "npx tsx server/db/sqlite/migrate.ts", - "db:studio": "drizzle-kit studio --config=./drizzle.config.ts", + "db:pg:studio": "drizzle-kit studio --config=./drizzle.pg.config.ts", + "db:sqlite:studio": "drizzle-kit studio --config=./drizzle.sqlite.config.ts", "db:clear-migrations": "rm -rf server/migrations", "set:oss": "echo 'export const build = \"oss\" as \"saas\" | \"enterprise\" | \"oss\";' > server/build.ts && cp tsconfig.oss.json tsconfig.json", "set:saas": "echo 'export const build = \"saas\" as \"saas\" | \"enterprise\" | \"oss\";' > server/build.ts && cp tsconfig.saas.json tsconfig.json", diff --git a/server/private/routers/remoteExitNode/createRemoteExitNode.ts b/server/private/routers/remoteExitNode/createRemoteExitNode.ts index f734813e..ed7b82a6 100644 --- a/server/private/routers/remoteExitNode/createRemoteExitNode.ts +++ b/server/private/routers/remoteExitNode/createRemoteExitNode.ts @@ -97,7 +97,7 @@ export async function createRemoteExitNode( return next( createHttpError( HttpCode.FORBIDDEN, - "Remote exit node limit exceeded. Please upgrade your plan or contact us at support@pangolin.net" + "Remote node limit exceeded. Please upgrade your plan." ) ); } diff --git a/server/routers/site/createSite.ts b/server/routers/site/createSite.ts index ece97d1d..d9837f30 100644 --- a/server/routers/site/createSite.ts +++ b/server/routers/site/createSite.ts @@ -151,7 +151,7 @@ export async function createSite( return next( createHttpError( HttpCode.FORBIDDEN, - "Sites limit exceeded. Please upgrade your plan." + "Site limit exceeded. Please upgrade your plan." ) ); } diff --git a/server/routers/user/acceptInvite.ts b/server/routers/user/acceptInvite.ts index d64ccfb5..fd79d849 100644 --- a/server/routers/user/acceptInvite.ts +++ b/server/routers/user/acceptInvite.ts @@ -13,6 +13,7 @@ import { verifySession } from "@server/auth/sessions/verifySession"; import { usageService } from "@server/lib/billing/usageService"; import { FeatureId } from "@server/lib/billing"; import { calculateUserClientsForOrgs } from "@server/lib/calculateUserClientsForOrgs"; +import { build } from "@server/build"; const acceptInviteBodySchema = z.strictObject({ token: z.string(), @@ -92,6 +93,35 @@ export async function acceptInvite( ); } + if (build == "saas") { + const usage = await usageService.getUsage(existingInvite.orgId, FeatureId.USERS); + if (!usage) { + return next( + createHttpError( + HttpCode.NOT_FOUND, + "No usage data found for this organization" + ) + ); + } + const rejectUsers = await usageService.checkLimitSet( + existingInvite.orgId, + false, + FeatureId.USERS, + { + ...usage, + instantaneousValue: (usage.instantaneousValue || 0) + 1 + } // We need to add one to know if we are violating the limit + ); + if (rejectUsers) { + return next( + createHttpError( + HttpCode.FORBIDDEN, + "Can not accept because this org's user limit is exceeded. Please contact your administrator to upgrade their plan." + ) + ); + } + } + let roleId: number; let totalUsers: UserOrg[] | undefined; // get the role to make sure it exists diff --git a/src/components/InviteStatusCard.tsx b/src/components/InviteStatusCard.tsx index d394bd57..417fa989 100644 --- a/src/components/InviteStatusCard.tsx +++ b/src/components/InviteStatusCard.tsx @@ -39,7 +39,7 @@ export default function InviteStatusCard({ const [loading, setLoading] = useState(true); const [error, setError] = useState(""); const [type, setType] = useState< - "rejected" | "wrong_user" | "user_does_not_exist" | "not_logged_in" + "rejected" | "wrong_user" | "user_does_not_exist" | "not_logged_in" | "user_limit_exceeded" >("rejected"); useEffect(() => { @@ -75,6 +75,11 @@ export default function InviteStatusCard({ error.includes("You must be logged in to accept an invite") ) { return "not_logged_in"; + } else if ( + error.includes("user limit is exceeded") || + error.includes("Can not accept") + ) { + return "user_limit_exceeded"; } else { return "rejected"; } @@ -145,6 +150,17 @@ export default function InviteStatusCard({
{t("inviteCreateUser")}
); + } else if (type === "user_limit_exceeded") { + return ( ++ Cannot Accept Invite +
++ This organization has reached its user limit. Please contact the organization administrator to upgrade their plan before accepting this invite. +
+