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:
Somay Chauhan 2023-12-18 18:09:27 +05:30 committed by GitHub
parent 2410f8b3aa
commit e1a9576530
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 2 deletions

View File

@ -1,4 +1,5 @@
import { BuildingIcon, PaperclipIcon, UserIcon, Users } from "lucide-react";
import { useSession } from "next-auth/react";
import { Trans } from "next-i18next";
import { useMemo, useState, useRef } from "react";
import type { FormEvent } from "react";
@ -70,6 +71,11 @@ export default function MemberInvitationModal(props: MemberInvitationModalProps)
const { t } = useLocale();
const { disableCopyLink = false, isOrg = false } = props;
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>(
props?.orgMembers && props.orgMembers?.length > 0 ? "ORGANIZATION" : "INDIVIDUAL"
@ -96,12 +102,19 @@ export default function MemberInvitationModal(props: MemberInvitationModalProps)
};
const options: MembershipRoleOption[] = useMemo(() => {
return [
const options: MembershipRoleOption[] = [
{ value: MembershipRole.MEMBER, label: t("member") },
{ value: MembershipRole.ADMIN, label: t("admin") },
{ 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 array = [

View File

@ -2,9 +2,13 @@ import { updateQuantitySubscriptionFromStripe } from "@calcom/features/ee/teams/
import { checkRateLimitAndThrowError } from "@calcom/lib/checkRateLimitAndThrowError";
import { IS_TEAM_BILLING_ENABLED } from "@calcom/lib/constants";
import { getTranslation } from "@calcom/lib/server/i18n";
import { isOrganisationOwner } from "@calcom/lib/server/queries/organisations";
import { prisma } from "@calcom/prisma";
import { MembershipRole } from "@calcom/prisma/enums";
import type { TrpcSessionUser } from "@calcom/trpc/server/trpc";
import { TRPCError } from "@trpc/server";
import type { TInviteMemberInputSchema } from "./inviteMember.schema";
import {
checkPermissions,
@ -40,6 +44,14 @@ export const inviteMemberHandler = async ({ ctx, input }: InviteMemberOptions) =
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 { autoAcceptEmailDomain, orgVerified } = getIsOrgVerified(input.isOrg, team);
const usernameOrEmailsToInvite = await getUsernameOrEmailsToInvite(input.usernameOrEmail);