fix: only owners can award owner role in an organization. (#12803)
* fix: only owners can award owner role in an organization. * chore: improve code --------- Co-authored-by: Udit Takkar <udit222001@gmail.com>
This commit is contained in:
parent
2410f8b3aa
commit
e1a9576530
|
@ -1,4 +1,5 @@
|
||||||
import { BuildingIcon, PaperclipIcon, UserIcon, Users } from "lucide-react";
|
import { BuildingIcon, PaperclipIcon, UserIcon, Users } from "lucide-react";
|
||||||
|
import { useSession } from "next-auth/react";
|
||||||
import { Trans } from "next-i18next";
|
import { Trans } from "next-i18next";
|
||||||
import { useMemo, useState, useRef } from "react";
|
import { useMemo, useState, useRef } from "react";
|
||||||
import type { FormEvent } from "react";
|
import type { FormEvent } from "react";
|
||||||
|
@ -70,6 +71,11 @@ export default function MemberInvitationModal(props: MemberInvitationModalProps)
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
const { disableCopyLink = false, isOrg = false } = props;
|
const { disableCopyLink = false, isOrg = false } = props;
|
||||||
const trpcContext = trpc.useContext();
|
const trpcContext = trpc.useContext();
|
||||||
|
const session = useSession();
|
||||||
|
const { data: currentOrg } = trpc.viewer.organizations.listCurrent.useQuery(undefined, {
|
||||||
|
enabled: !!session.data?.user?.org,
|
||||||
|
});
|
||||||
|
const isOrgOwner = currentOrg && currentOrg.user.role === MembershipRole.OWNER;
|
||||||
|
|
||||||
const [modalImportMode, setModalInputMode] = useState<ModalMode>(
|
const [modalImportMode, setModalInputMode] = useState<ModalMode>(
|
||||||
props?.orgMembers && props.orgMembers?.length > 0 ? "ORGANIZATION" : "INDIVIDUAL"
|
props?.orgMembers && props.orgMembers?.length > 0 ? "ORGANIZATION" : "INDIVIDUAL"
|
||||||
|
@ -96,12 +102,19 @@ export default function MemberInvitationModal(props: MemberInvitationModalProps)
|
||||||
};
|
};
|
||||||
|
|
||||||
const options: MembershipRoleOption[] = useMemo(() => {
|
const options: MembershipRoleOption[] = useMemo(() => {
|
||||||
return [
|
const options: MembershipRoleOption[] = [
|
||||||
{ value: MembershipRole.MEMBER, label: t("member") },
|
{ value: MembershipRole.MEMBER, label: t("member") },
|
||||||
{ value: MembershipRole.ADMIN, label: t("admin") },
|
{ value: MembershipRole.ADMIN, label: t("admin") },
|
||||||
{ value: MembershipRole.OWNER, label: t("owner") },
|
{ value: MembershipRole.OWNER, label: t("owner") },
|
||||||
];
|
];
|
||||||
}, [t]);
|
|
||||||
|
// Adjust options for organizations where the user isn't the owner
|
||||||
|
if (isOrg && !isOrgOwner) {
|
||||||
|
return options.filter((option) => option.value !== MembershipRole.OWNER);
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}, [t, isOrgOwner, isOrg]);
|
||||||
|
|
||||||
const toggleGroupOptions = useMemo(() => {
|
const toggleGroupOptions = useMemo(() => {
|
||||||
const array = [
|
const array = [
|
||||||
|
|
|
@ -2,9 +2,13 @@ import { updateQuantitySubscriptionFromStripe } from "@calcom/features/ee/teams/
|
||||||
import { checkRateLimitAndThrowError } from "@calcom/lib/checkRateLimitAndThrowError";
|
import { checkRateLimitAndThrowError } from "@calcom/lib/checkRateLimitAndThrowError";
|
||||||
import { IS_TEAM_BILLING_ENABLED } from "@calcom/lib/constants";
|
import { IS_TEAM_BILLING_ENABLED } from "@calcom/lib/constants";
|
||||||
import { getTranslation } from "@calcom/lib/server/i18n";
|
import { getTranslation } from "@calcom/lib/server/i18n";
|
||||||
|
import { isOrganisationOwner } from "@calcom/lib/server/queries/organisations";
|
||||||
import { prisma } from "@calcom/prisma";
|
import { prisma } from "@calcom/prisma";
|
||||||
|
import { MembershipRole } from "@calcom/prisma/enums";
|
||||||
import type { TrpcSessionUser } from "@calcom/trpc/server/trpc";
|
import type { TrpcSessionUser } from "@calcom/trpc/server/trpc";
|
||||||
|
|
||||||
|
import { TRPCError } from "@trpc/server";
|
||||||
|
|
||||||
import type { TInviteMemberInputSchema } from "./inviteMember.schema";
|
import type { TInviteMemberInputSchema } from "./inviteMember.schema";
|
||||||
import {
|
import {
|
||||||
checkPermissions,
|
checkPermissions,
|
||||||
|
@ -40,6 +44,14 @@ export const inviteMemberHandler = async ({ ctx, input }: InviteMemberOptions) =
|
||||||
isOrg: input.isOrg,
|
isOrg: input.isOrg,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Only owners can award owner role in an organization.
|
||||||
|
if (
|
||||||
|
input.isOrg &&
|
||||||
|
input.role === MembershipRole.OWNER &&
|
||||||
|
!(await isOrganisationOwner(ctx.user.id, input.teamId))
|
||||||
|
)
|
||||||
|
throw new TRPCError({ code: "UNAUTHORIZED" });
|
||||||
|
|
||||||
const team = await getTeamOrThrow(input.teamId, input.isOrg);
|
const team = await getTeamOrThrow(input.teamId, input.isOrg);
|
||||||
const { autoAcceptEmailDomain, orgVerified } = getIsOrgVerified(input.isOrg, team);
|
const { autoAcceptEmailDomain, orgVerified } = getIsOrgVerified(input.isOrg, team);
|
||||||
const usernameOrEmailsToInvite = await getUsernameOrEmailsToInvite(input.usernameOrEmail);
|
const usernameOrEmailsToInvite = await getUsernameOrEmailsToInvite(input.usernameOrEmail);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user