Add restrictions to protect the owners and change their roles
This commit is contained in:
parent
82f7779a23
commit
3234898892
3 changed files with 29 additions and 7 deletions
apps/web/components/team
|
@ -5,6 +5,7 @@ import React, { SyntheticEvent, useEffect } from "react";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import Button from "@calcom/ui/Button";
|
import Button from "@calcom/ui/Button";
|
||||||
|
|
||||||
|
import { TeamWithMembers } from "@lib/queries/teams";
|
||||||
import { trpc } from "@lib/trpc";
|
import { trpc } from "@lib/trpc";
|
||||||
|
|
||||||
import ModalContainer from "@components/ui/ModalContainer";
|
import ModalContainer from "@components/ui/ModalContainer";
|
||||||
|
@ -15,10 +16,11 @@ type MembershipRoleOption = {
|
||||||
label?: string;
|
label?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const options: MembershipRoleOption[] = [{ value: "MEMBER" }, { value: "ADMIN" }];
|
const options: MembershipRoleOption[] = [{ value: "MEMBER" }, { value: "ADMIN" }, { value: "OWNER" }];
|
||||||
|
|
||||||
export default function MemberChangeRoleModal(props: {
|
export default function MemberChangeRoleModal(props: {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
|
team: TeamWithMembers;
|
||||||
memberId: number;
|
memberId: number;
|
||||||
teamId: number;
|
teamId: number;
|
||||||
initialRole: MembershipRole;
|
initialRole: MembershipRole;
|
||||||
|
@ -48,6 +50,8 @@ export default function MemberChangeRoleModal(props: {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const memberRole = props.team?.membership.role;
|
||||||
|
|
||||||
function changeRole(e: SyntheticEvent) {
|
function changeRole(e: SyntheticEvent) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
@ -57,7 +61,6 @@ export default function MemberChangeRoleModal(props: {
|
||||||
role: role.value,
|
role: role.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalContainer isOpen={props.isOpen} onExit={props.onExit}>
|
<ModalContainer isOpen={props.isOpen} onExit={props.onExit}>
|
||||||
<>
|
<>
|
||||||
|
@ -76,7 +79,7 @@ export default function MemberChangeRoleModal(props: {
|
||||||
{/*<option value="OWNER">{t("owner")}</option> - needs dialog to confirm change of ownership */}
|
{/*<option value="OWNER">{t("owner")}</option> - needs dialog to confirm change of ownership */}
|
||||||
<Select
|
<Select
|
||||||
isSearchable={false}
|
isSearchable={false}
|
||||||
options={options}
|
options={memberRole !== MembershipRole.OWNER ? options.slice(0, 2) : options}
|
||||||
value={role}
|
value={role}
|
||||||
onChange={(option) => option && setRole(option)}
|
onChange={(option) => option && setRole(option)}
|
||||||
id="role"
|
id="role"
|
||||||
|
|
|
@ -24,7 +24,7 @@ type MembershipRoleOption = {
|
||||||
label?: string;
|
label?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const _options: MembershipRoleOption[] = [{ value: "MEMBER" }, { value: "ADMIN" }];
|
const _options: MembershipRoleOption[] = [{ value: "MEMBER" }, { value: "ADMIN" }, { value: "OWNER" }];
|
||||||
|
|
||||||
export default function MemberInvitationModal(props: MemberInvitationModalProps) {
|
export default function MemberInvitationModal(props: MemberInvitationModalProps) {
|
||||||
const [errorMessage, setErrorMessage] = useState("");
|
const [errorMessage, setErrorMessage] = useState("");
|
||||||
|
@ -48,6 +48,8 @@ export default function MemberInvitationModal(props: MemberInvitationModalProps)
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const memberRole = props.team?.membership.role;
|
||||||
|
|
||||||
function inviteMember(e: SyntheticEvent) {
|
function inviteMember(e: SyntheticEvent) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!props.team) return;
|
if (!props.team) return;
|
||||||
|
@ -100,7 +102,7 @@ export default function MemberInvitationModal(props: MemberInvitationModalProps)
|
||||||
</label>
|
</label>
|
||||||
<Select
|
<Select
|
||||||
defaultValue={options[0]}
|
defaultValue={options[0]}
|
||||||
options={options}
|
options={memberRole !== MembershipRole.OWNER ? options.slice(0, 2) : options}
|
||||||
id="role"
|
id="role"
|
||||||
name="role"
|
name="role"
|
||||||
className="mt-1 block w-full rounded-sm border-gray-300 shadow-sm sm:text-sm"
|
className="mt-1 block w-full rounded-sm border-gray-300 shadow-sm sm:text-sm"
|
||||||
|
|
|
@ -24,6 +24,7 @@ import ConfirmationDialogContent from "@components/dialog/ConfirmationDialogCont
|
||||||
import Avatar from "@components/ui/Avatar";
|
import Avatar from "@components/ui/Avatar";
|
||||||
import ModalContainer from "@components/ui/ModalContainer";
|
import ModalContainer from "@components/ui/ModalContainer";
|
||||||
|
|
||||||
|
import { useMeQuery } from "../Shell";
|
||||||
import MemberChangeRoleModal from "./MemberChangeRoleModal";
|
import MemberChangeRoleModal from "./MemberChangeRoleModal";
|
||||||
import TeamPill, { TeamRole } from "./TeamPill";
|
import TeamPill, { TeamRole } from "./TeamPill";
|
||||||
|
|
||||||
|
@ -49,6 +50,20 @@ export default function MemberListItem(props: Props) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const ownersInTeam = () => {
|
||||||
|
const { members } = props.team;
|
||||||
|
const owners = members.filter((member) => member["role"] === "OWNER");
|
||||||
|
return owners.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useCurrentUser = () => {
|
||||||
|
const query = useMeQuery();
|
||||||
|
const user = query.data;
|
||||||
|
return user?.id;
|
||||||
|
};
|
||||||
|
|
||||||
|
const currentUser = useCurrentUser();
|
||||||
|
|
||||||
const name =
|
const name =
|
||||||
props.member.name ||
|
props.member.name ||
|
||||||
(() => {
|
(() => {
|
||||||
|
@ -121,8 +136,9 @@ export default function MemberListItem(props: Props) {
|
||||||
</Link>
|
</Link>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuSeparator className="h-px bg-gray-200" />
|
<DropdownMenuSeparator className="h-px bg-gray-200" />
|
||||||
{(props.team.membership.role === MembershipRole.OWNER ||
|
{((props.team.membership.role === MembershipRole.OWNER &&
|
||||||
props.team.membership.role === MembershipRole.ADMIN) && (
|
(props.member.role !== "OWNER" || (ownersInTeam() > 1 && props.member.id === currentUser))) ||
|
||||||
|
(props.team.membership.role === MembershipRole.ADMIN && props.member.role !== "OWNER")) && (
|
||||||
<>
|
<>
|
||||||
<DropdownMenuItem>
|
<DropdownMenuItem>
|
||||||
<Button
|
<Button
|
||||||
|
@ -165,6 +181,7 @@ export default function MemberListItem(props: Props) {
|
||||||
{showChangeMemberRoleModal && (
|
{showChangeMemberRoleModal && (
|
||||||
<MemberChangeRoleModal
|
<MemberChangeRoleModal
|
||||||
isOpen={showChangeMemberRoleModal}
|
isOpen={showChangeMemberRoleModal}
|
||||||
|
team={props.team}
|
||||||
teamId={props.team?.id}
|
teamId={props.team?.id}
|
||||||
memberId={props.member.id}
|
memberId={props.member.id}
|
||||||
initialRole={props.member.role as MembershipRole}
|
initialRole={props.member.role as MembershipRole}
|
||||||
|
|
Loading…
Reference in a new issue