Block inviting members to organization if SAML SSO is configured

This commit is contained in:
Tuan Dang
2023-07-23 13:05:37 +07:00
parent 5b36227321
commit 39ba795604
4 changed files with 47 additions and 4 deletions
@@ -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";
@@ -111,6 +112,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
@@ -59,6 +60,12 @@ export const updateSSOConfig = async (req: Request, res: Response) => {
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;
isActive?: boolean; isActive?: boolean;
@@ -204,6 +211,12 @@ export const createSSOConfig = async (req: Request, res: Response) => {
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();
@@ -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 {