Compare commits

...

7 Commits

Author SHA1 Message Date
Scott Wilson
a4eb2e77c2 improvement: move client instantation to try/catch for sql connection validation for error propogation 2025-04-21 13:49:09 -07:00
Scott Wilson
35f0e8f49a Merge pull request #3456 from Infisical/fix/secretVersionReferenceIssue
Fix SecretVersionV2 reference issue blocking users and identities deletion
2025-04-21 10:20:54 -07:00
Akhil Mohan
b4226e7e1b Merge pull request #3427 from akhilmhdh/feat/block-user-on-trail
Block user on crossing the identity limit
2025-04-21 20:06:22 +05:30
=
7364717f60 feat: added an additional 10 as threshold 2025-04-18 22:35:41 +05:30
=
5b20c1feba feat: reptile jaw spaced 2025-04-16 00:30:11 +05:30
=
ac73800acb feat: added banner on crossing user/identity limit 2025-04-16 00:25:21 +05:30
=
dd323eccd4 feat: added banner on projects when limit reached 2025-04-15 22:00:22 +05:30
2 changed files with 33 additions and 7 deletions

View File

@@ -77,20 +77,22 @@ export const getSqlConnectionClient = async (appConnection: Pick<TSqlConnection,
export const validateSqlConnectionCredentials = async (config: TSqlConnectionConfig) => {
const { credentials, app } = config;
const client = await getSqlConnectionClient({ app, credentials });
let client: Knex | undefined;
try {
client = await getSqlConnectionClient({ app, credentials });
await client.raw(`Select 1`);
return credentials;
} catch (error) {
throw new BadRequestError({
message:
(error as Error)?.message?.replaceAll(credentials.password, "********************") ??
"Unable to validate connection: verify credentials"
message: `Unable to validate connection: ${
(error as Error)?.message?.replaceAll(credentials.password, "********************") ?? "verify credentials"
}`
});
} finally {
await client.destroy();
await client?.destroy();
}
};

View File

@@ -1,9 +1,10 @@
import { useTranslation } from "react-i18next";
import { faMobile } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Link, Outlet, useRouterState } from "@tanstack/react-router";
import { Link, Outlet, useNavigate, useRouterState } from "@tanstack/react-router";
import { motion } from "framer-motion";
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
import {
BreadcrumbContainer,
Menu,
@@ -31,6 +32,19 @@ export const ProjectLayout = () => {
const { t } = useTranslation();
const workspaceId = currentWorkspace?.id || "";
const projectSlug = currentWorkspace?.slug || "";
const { subscription } = useSubscription();
const navigate = useNavigate();
const hasIdentityLimitCrossed =
subscription?.identityLimit && subscription?.identitiesUsed > subscription.identityLimit + 10;
const hasUserLimitCrossed =
subscription?.memberLimit && subscription?.membersUsed > subscription.memberLimit + 10;
const shouldUpgrade = Boolean(hasUserLimitCrossed || hasIdentityLimitCrossed);
let upgradeText = "";
if (hasUserLimitCrossed) {
upgradeText = `You've reached the maximum number of organisation users (${subscription?.memberLimit}).`;
} else if (hasIdentityLimitCrossed) {
upgradeText = `You've reached the maximum number of organisation identities (${subscription?.identityLimit}).`;
}
const isSecretManager = currentWorkspace?.type === ProjectType.SecretManager;
const isCertManager = currentWorkspace?.type === ProjectType.CertificateManager;
@@ -47,7 +61,6 @@ export const ProjectLayout = () => {
});
// we only show the secret rotations v1 tab if they have existing rotations
const { subscription } = useSubscription();
const { data: secretRotations } = useGetSecretRotations({
workspaceId,
options: {
@@ -267,6 +280,17 @@ export const ProjectLayout = () => {
</div>
</div>
</div>
{shouldUpgrade && (
<UpgradePlanModal
isOpen={shouldUpgrade}
text={upgradeText}
onOpenChange={(isOpen) => {
if (!isOpen) {
navigate({ to: "/organization/access-management" });
}
}}
/>
)}
<div className="z-[200] flex h-screen w-screen flex-col items-center justify-center bg-bunker-800 md:hidden">
<FontAwesomeIcon icon={faMobile} className="mb-8 text-7xl text-gray-300" />
<p className="max-w-sm px-6 text-center text-lg text-gray-200">