mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 18:27:19 +00:00
Block inviting members to organization if SAML SSO is configured
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { Types } from "mongoose";
|
import { Types } from "mongoose";
|
||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import { MembershipOrg, Organization, User } from "../../models";
|
import { MembershipOrg, Organization, User } from "../../models";
|
||||||
|
import { SSOConfig } from "../../ee/models";
|
||||||
import { deleteMembershipOrg as deleteMemberFromOrg } from "../../helpers/membershipOrg";
|
import { deleteMembershipOrg as deleteMemberFromOrg } from "../../helpers/membershipOrg";
|
||||||
import { createToken } from "../../helpers/auth";
|
import { createToken } from "../../helpers/auth";
|
||||||
import { updateSubscriptionOrgQuantity } from "../../helpers/organization";
|
import { updateSubscriptionOrgQuantity } from "../../helpers/organization";
|
||||||
@@ -110,6 +111,18 @@ export const inviteUserToOrganization = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const plan = await EELicenseService.getPlan(organizationId);
|
const plan = await EELicenseService.getPlan(organizationId);
|
||||||
|
|
||||||
|
const ssoConfig = await SSOConfig.findOne({
|
||||||
|
organization: new Types.ObjectId(organizationId)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ssoConfig && ssoConfig.isActive) {
|
||||||
|
// case: SAML SSO is enabled for the organization
|
||||||
|
return res.status(400).send({
|
||||||
|
message:
|
||||||
|
"Failed to invite member due to SAML SSO configured for organization"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (plan.memberLimit !== null) {
|
if (plan.memberLimit !== null) {
|
||||||
// case: limit imposed on number of members allowed
|
// case: limit imposed on number of members allowed
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { getSSOConfigHelper } from "../../helpers/organizations";
|
|||||||
import { client } from "../../../config";
|
import { client } from "../../../config";
|
||||||
import { ResourceNotFoundError } from "../../../utils/errors";
|
import { ResourceNotFoundError } from "../../../utils/errors";
|
||||||
import { getSiteURL } from "../../../config";
|
import { getSiteURL } from "../../../config";
|
||||||
|
import { EELicenseService } from "../../services";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redirect user to appropriate SSO endpoint after successful authentication
|
* Redirect user to appropriate SSO endpoint after successful authentication
|
||||||
@@ -58,6 +59,12 @@ export const updateSSOConfig = async (req: Request, res: Response) => {
|
|||||||
cert,
|
cert,
|
||||||
audience
|
audience
|
||||||
} = req.body;
|
} = req.body;
|
||||||
|
|
||||||
|
const plan = await EELicenseService.getPlan(organizationId);
|
||||||
|
|
||||||
|
if (!plan.samlSSO) return res.status(400).send({
|
||||||
|
message: "Failed to update SAML SSO configuration due to plan restriction. Upgrade plan to update SSO configuration."
|
||||||
|
});
|
||||||
|
|
||||||
interface PatchUpdate {
|
interface PatchUpdate {
|
||||||
authProvider?: string;
|
authProvider?: string;
|
||||||
@@ -203,6 +210,12 @@ export const createSSOConfig = async (req: Request, res: Response) => {
|
|||||||
cert,
|
cert,
|
||||||
audience
|
audience
|
||||||
} = req.body;
|
} = req.body;
|
||||||
|
|
||||||
|
const plan = await EELicenseService.getPlan(organizationId);
|
||||||
|
|
||||||
|
if (!plan.samlSSO) return res.status(400).send({
|
||||||
|
message: "Failed to create SAML SSO configuration due to plan restriction. Upgrade plan to add SSO configuration."
|
||||||
|
});
|
||||||
|
|
||||||
const key = await BotOrgService.getSymmetricKey(
|
const key = await BotOrgService.getSymmetricKey(
|
||||||
new Types.ObjectId(organizationId)
|
new Types.ObjectId(organizationId)
|
||||||
|
|||||||
@@ -183,7 +183,9 @@ export default function Users() {
|
|||||||
<div className="ml-2 flex min-w-max flex-row items-start justify-start">
|
<div className="ml-2 flex min-w-max flex-row items-start justify-start">
|
||||||
<Button
|
<Button
|
||||||
text={String(t("section.members.add-member"))}
|
text={String(t("section.members.add-member"))}
|
||||||
onButtonPressed={openAddModal}
|
onButtonPressed={() => {
|
||||||
|
openAddModal();
|
||||||
|
}}
|
||||||
color="mineshaft"
|
color="mineshaft"
|
||||||
size="md"
|
size="md"
|
||||||
icon={faPlus}
|
icon={faPlus}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
|
|
||||||
|
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
DeleteActionModal,
|
DeleteActionModal,
|
||||||
@@ -26,9 +27,11 @@ import {
|
|||||||
Th,
|
Th,
|
||||||
THead,
|
THead,
|
||||||
Tr,
|
Tr,
|
||||||
UpgradePlanModal} from "@app/components/v2";
|
UpgradePlanModal
|
||||||
import { useWorkspace } from "@app/context";
|
} from "@app/components/v2";
|
||||||
|
import { useOrganization , useWorkspace } from "@app/context";
|
||||||
import { usePopUp, useToggle } from "@app/hooks";
|
import { usePopUp, useToggle } from "@app/hooks";
|
||||||
|
import { useGetSSOConfig } from "@app/hooks/api";
|
||||||
import { useFetchServerStatus } from "@app/hooks/api/serverDetails";
|
import { useFetchServerStatus } from "@app/hooks/api/serverDetails";
|
||||||
import { OrgUser, Workspace } from "@app/hooks/api/types";
|
import { OrgUser, Workspace } from "@app/hooks/api/types";
|
||||||
|
|
||||||
@@ -69,6 +72,9 @@ export const OrgMembersTable = ({
|
|||||||
setCompleteInviteLink
|
setCompleteInviteLink
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const { createNotification } = useNotificationContext();
|
||||||
|
const { currentOrg } = useOrganization();
|
||||||
|
const { data: ssoConfig, isLoading: isLoadingSSOConfig } = useGetSSOConfig(currentOrg?._id ?? "");
|
||||||
const [searchMemberFilter, setSearchMemberFilter] = useState("");
|
const [searchMemberFilter, setSearchMemberFilter] = useState("");
|
||||||
const {data: serverDetails } = useFetchServerStatus()
|
const {data: serverDetails } = useFetchServerStatus()
|
||||||
const { workspaces } = useWorkspace();
|
const { workspaces } = useWorkspace();
|
||||||
@@ -79,7 +85,7 @@ export const OrgMembersTable = ({
|
|||||||
"upgradePlan",
|
"upgradePlan",
|
||||||
"setUpEmail"
|
"setUpEmail"
|
||||||
] as const);
|
] as const);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (router.query.action === "invite") {
|
if (router.query.action === "invite") {
|
||||||
handlePopUpOpen("addMember");
|
handlePopUpOpen("addMember");
|
||||||
@@ -152,6 +158,15 @@ export const OrgMembersTable = ({
|
|||||||
<Button
|
<Button
|
||||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (!isLoadingSSOConfig && ssoConfig && ssoConfig.isActive) {
|
||||||
|
createNotification({
|
||||||
|
text: "You cannot invite users when SAML SSO is configured for your organization",
|
||||||
|
type: "error"
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isMoreUserNotAllowed) {
|
if (isMoreUserNotAllowed) {
|
||||||
handlePopUpOpen("upgradePlan");
|
handlePopUpOpen("upgradePlan");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user