mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-10 20:02:26 +00:00
Dont accept invite if over the limits
This commit is contained in:
@@ -18,7 +18,8 @@
|
|||||||
"db:sqlite:generate": "drizzle-kit generate --config=./drizzle.sqlite.config.ts",
|
"db:sqlite:generate": "drizzle-kit generate --config=./drizzle.sqlite.config.ts",
|
||||||
"db:pg:push": "npx tsx server/db/pg/migrate.ts",
|
"db:pg:push": "npx tsx server/db/pg/migrate.ts",
|
||||||
"db:sqlite:push": "npx tsx server/db/sqlite/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",
|
"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: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",
|
"set:saas": "echo 'export const build = \"saas\" as \"saas\" | \"enterprise\" | \"oss\";' > server/build.ts && cp tsconfig.saas.json tsconfig.json",
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export async function createRemoteExitNode(
|
|||||||
return next(
|
return next(
|
||||||
createHttpError(
|
createHttpError(
|
||||||
HttpCode.FORBIDDEN,
|
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."
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ export async function createSite(
|
|||||||
return next(
|
return next(
|
||||||
createHttpError(
|
createHttpError(
|
||||||
HttpCode.FORBIDDEN,
|
HttpCode.FORBIDDEN,
|
||||||
"Sites limit exceeded. Please upgrade your plan."
|
"Site limit exceeded. Please upgrade your plan."
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { verifySession } from "@server/auth/sessions/verifySession";
|
|||||||
import { usageService } from "@server/lib/billing/usageService";
|
import { usageService } from "@server/lib/billing/usageService";
|
||||||
import { FeatureId } from "@server/lib/billing";
|
import { FeatureId } from "@server/lib/billing";
|
||||||
import { calculateUserClientsForOrgs } from "@server/lib/calculateUserClientsForOrgs";
|
import { calculateUserClientsForOrgs } from "@server/lib/calculateUserClientsForOrgs";
|
||||||
|
import { build } from "@server/build";
|
||||||
|
|
||||||
const acceptInviteBodySchema = z.strictObject({
|
const acceptInviteBodySchema = z.strictObject({
|
||||||
token: z.string(),
|
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 roleId: number;
|
||||||
let totalUsers: UserOrg[] | undefined;
|
let totalUsers: UserOrg[] | undefined;
|
||||||
// get the role to make sure it exists
|
// get the role to make sure it exists
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export default function InviteStatusCard({
|
|||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
const [type, setType] = 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");
|
>("rejected");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -75,6 +75,11 @@ export default function InviteStatusCard({
|
|||||||
error.includes("You must be logged in to accept an invite")
|
error.includes("You must be logged in to accept an invite")
|
||||||
) {
|
) {
|
||||||
return "not_logged_in";
|
return "not_logged_in";
|
||||||
|
} else if (
|
||||||
|
error.includes("user limit is exceeded") ||
|
||||||
|
error.includes("Can not accept")
|
||||||
|
) {
|
||||||
|
return "user_limit_exceeded";
|
||||||
} else {
|
} else {
|
||||||
return "rejected";
|
return "rejected";
|
||||||
}
|
}
|
||||||
@@ -145,6 +150,17 @@ export default function InviteStatusCard({
|
|||||||
<p className="text-center">{t("inviteCreateUser")}</p>
|
<p className="text-center">{t("inviteCreateUser")}</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
} else if (type === "user_limit_exceeded") {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p className="text-center mb-4 font-semibold">
|
||||||
|
Cannot Accept Invite
|
||||||
|
</p>
|
||||||
|
<p className="text-center text-sm">
|
||||||
|
This organization has reached its user limit. Please contact the organization administrator to upgrade their plan before accepting this invite.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,6 +181,16 @@ export default function InviteStatusCard({
|
|||||||
);
|
);
|
||||||
} else if (type === "user_does_not_exist") {
|
} else if (type === "user_does_not_exist") {
|
||||||
return <Button onClick={goToSignup}>{t("createAnAccount")}</Button>;
|
return <Button onClick={goToSignup}>{t("createAnAccount")}</Button>;
|
||||||
|
} else if (type === "user_limit_exceeded") {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
router.push("/");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("goHome")}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user