Patch for update org membership call, hide edit user on self user page

This commit is contained in:
Tuan Dang
2024-07-18 20:40:12 +07:00
parent 20387cff35
commit 43b14d0091
3 changed files with 123 additions and 110 deletions
+5 -2
View File
@@ -57,7 +57,7 @@ type TOrgServiceFactoryDep = {
projectDAL: TProjectDALFactory; projectDAL: TProjectDALFactory;
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "findProjectMembershipsByUserId" | "delete">; projectMembershipDAL: Pick<TProjectMembershipDALFactory, "findProjectMembershipsByUserId" | "delete">;
projectKeyDAL: Pick<TProjectKeyDALFactory, "find" | "delete">; projectKeyDAL: Pick<TProjectKeyDALFactory, "find" | "delete">;
orgMembershipDAL: Pick<TOrgMembershipDALFactory, "findOrgMembershipById">; orgMembershipDAL: Pick<TOrgMembershipDALFactory, "findOrgMembershipById" | "findOne">;
incidentContactDAL: TIncidentContactsDALFactory; incidentContactDAL: TIncidentContactsDALFactory;
samlConfigDAL: Pick<TSamlConfigDALFactory, "findOne" | "findEnforceableSamlCfg">; samlConfigDAL: Pick<TSamlConfigDALFactory, "findOne" | "findEnforceableSamlCfg">;
smtpService: TSmtpService; smtpService: TSmtpService;
@@ -379,7 +379,10 @@ export const orgServiceFactory = ({
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId); const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Member); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Member);
const [foundMembership] = await orgDAL.findMembership({ id: membershipId, orgId }); const foundMembership = await orgMembershipDAL.findOne({
id: membershipId,
orgId
});
if (!foundMembership) throw new NotFoundError({ message: "Failed to find organization membership" }); if (!foundMembership) throw new NotFoundError({ message: "Failed to find organization membership" });
if (foundMembership.userId === userId) if (foundMembership.userId === userId)
throw new BadRequestError({ message: "Cannot update own organization membership" }); throw new BadRequestError({ message: "Cannot update own organization membership" });
+116 -106
View File
@@ -16,7 +16,12 @@ import {
Tooltip, Tooltip,
UpgradePlanModal UpgradePlanModal
} from "@app/components/v2"; } from "@app/components/v2";
import { OrgPermissionActions, OrgPermissionSubjects, useOrganization } from "@app/context"; import {
OrgPermissionActions,
OrgPermissionSubjects,
useOrganization,
useUser
} from "@app/context";
import { withPermission } from "@app/hoc"; import { withPermission } from "@app/hoc";
import { import {
useDeleteOrgMembership, useDeleteOrgMembership,
@@ -31,7 +36,10 @@ export const UserPage = withPermission(
() => { () => {
const router = useRouter(); const router = useRouter();
const membershipId = router.query.membershipId as string; const membershipId = router.query.membershipId as string;
const { user } = useUser();
const { currentOrg } = useOrganization(); const { currentOrg } = useOrganization();
const userId = user?.id || "";
const orgId = currentOrg?.id || ""; const orgId = currentOrg?.id || "";
const { data: membership } = useGetOrgMembership(orgId, membershipId); const { data: membership } = useGetOrgMembership(orgId, membershipId);
@@ -115,116 +123,118 @@ export const UserPage = withPermission(
? `${membership.user.firstName} ${membership.user.lastName}` ? `${membership.user.firstName} ${membership.user.lastName}`
: "-"} : "-"}
</p> </p>
<DropdownMenu> {userId !== membership.user.id && (
<DropdownMenuTrigger asChild className="rounded-lg"> <DropdownMenu>
<div className="hover:text-primary-400 data-[state=open]:text-primary-400"> <DropdownMenuTrigger asChild className="rounded-lg">
<Tooltip content="More options"> <div className="hover:text-primary-400 data-[state=open]:text-primary-400">
<FontAwesomeIcon size="sm" icon={faEllipsis} /> <Tooltip content="More options">
</Tooltip> <FontAwesomeIcon size="sm" icon={faEllipsis} />
</div> </Tooltip>
</DropdownMenuTrigger> </div>
<DropdownMenuContent align="start" className="p-1"> </DropdownMenuTrigger>
<OrgPermissionCan <DropdownMenuContent align="start" className="p-1">
I={OrgPermissionActions.Edit} <OrgPermissionCan
a={OrgPermissionSubjects.Identity} I={OrgPermissionActions.Edit}
> a={OrgPermissionSubjects.Identity}
{(isAllowed) => ( >
<DropdownMenuItem {(isAllowed) => (
className={twMerge( <DropdownMenuItem
!isAllowed && "pointer-events-none cursor-not-allowed opacity-50" className={twMerge(
)} !isAllowed && "pointer-events-none cursor-not-allowed opacity-50"
onClick={() => )}
handlePopUpOpen("orgMembership", { onClick={() =>
membershipId: membership.id, handlePopUpOpen("orgMembership", {
role: membership.role membershipId: membership.id,
}) role: membership.role
} })
disabled={!isAllowed}
>
Edit User
</DropdownMenuItem>
)}
</OrgPermissionCan>
<OrgPermissionCan
I={OrgPermissionActions.Delete}
a={OrgPermissionSubjects.Member}
>
{(isAllowed) => (
<DropdownMenuItem
className={
membership.isActive
? twMerge(
isAllowed
? "hover:!bg-red-500 hover:!text-white"
: "pointer-events-none cursor-not-allowed opacity-50"
)
: ""
}
onClick={async () => {
if (currentOrg?.scimEnabled) {
createNotification({
text: "You cannot manage users from Infisical when SCIM is enabled for your organization",
type: "error"
});
return;
} }
disabled={!isAllowed}
if (!membership.isActive) { >
// activate user Edit User
await updateOrgMembership({ </DropdownMenuItem>
organizationId: orgId, )}
membershipId, </OrgPermissionCan>
isActive: true <OrgPermissionCan
}); I={OrgPermissionActions.Delete}
a={OrgPermissionSubjects.Member}
return; >
{(isAllowed) => (
<DropdownMenuItem
className={
membership.isActive
? twMerge(
isAllowed
? "hover:!bg-red-500 hover:!text-white"
: "pointer-events-none cursor-not-allowed opacity-50"
)
: ""
} }
onClick={async () => {
if (currentOrg?.scimEnabled) {
createNotification({
text: "You cannot manage users from Infisical when SCIM is enabled for your organization",
type: "error"
});
return;
}
// deactivate user if (!membership.isActive) {
handlePopUpOpen("deactivateMember", { // activate user
orgMembershipId: membershipId, await updateOrgMembership({
username: membership.user.username organizationId: orgId,
}); membershipId,
}} isActive: true
disabled={!isAllowed} });
>
{`${membership.isActive ? "Deactivate" : "Activate"} User`} return;
</DropdownMenuItem> }
)}
</OrgPermissionCan> // deactivate user
<OrgPermissionCan handlePopUpOpen("deactivateMember", {
I={OrgPermissionActions.Delete} orgMembershipId: membershipId,
a={OrgPermissionSubjects.Member} username: membership.user.username
>
{(isAllowed) => (
<DropdownMenuItem
className={twMerge(
isAllowed
? "hover:!bg-red-500 hover:!text-white"
: "pointer-events-none cursor-not-allowed opacity-50"
)}
onClick={() => {
if (currentOrg?.scimEnabled) {
createNotification({
text: "You cannot manage users from Infisical when SCIM is enabled for your organization",
type: "error"
}); });
return; }}
} disabled={!isAllowed}
>
{`${membership.isActive ? "Deactivate" : "Activate"} User`}
</DropdownMenuItem>
)}
</OrgPermissionCan>
<OrgPermissionCan
I={OrgPermissionActions.Delete}
a={OrgPermissionSubjects.Member}
>
{(isAllowed) => (
<DropdownMenuItem
className={twMerge(
isAllowed
? "hover:!bg-red-500 hover:!text-white"
: "pointer-events-none cursor-not-allowed opacity-50"
)}
onClick={() => {
if (currentOrg?.scimEnabled) {
createNotification({
text: "You cannot manage users from Infisical when SCIM is enabled for your organization",
type: "error"
});
return;
}
handlePopUpOpen("removeMember", { handlePopUpOpen("removeMember", {
orgMembershipId: membershipId, orgMembershipId: membershipId,
username: membership.user.username username: membership.user.username
}); });
}} }}
disabled={!isAllowed} disabled={!isAllowed}
> >
Remove User Remove User
</DropdownMenuItem> </DropdownMenuItem>
)} )}
</OrgPermissionCan> </OrgPermissionCan>
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
)}
</div> </div>
<div className="flex"> <div className="flex">
<div className="mr-4 w-96"> <div className="mr-4 w-96">
@@ -3,7 +3,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { createNotification } from "@app/components/notifications"; import { createNotification } from "@app/components/notifications";
import { DeleteActionModal, IconButton } from "@app/components/v2"; import { DeleteActionModal, IconButton } from "@app/components/v2";
import { useOrganization,useUser } from "@app/context"; import { useOrganization, useUser } from "@app/context";
import { useDeleteUserFromWorkspace, useGetOrgMembership } from "@app/hooks/api"; import { useDeleteUserFromWorkspace, useGetOrgMembership } from "@app/hooks/api";
import { usePopUp } from "@app/hooks/usePopUp"; import { usePopUp } from "@app/hooks/usePopUp";
@@ -51,7 +51,7 @@ export const UserProjectsSection = ({ membershipId }: Props) => {
<div className="w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4"> <div className="w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4"> <div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
<h3 className="text-lg font-semibold text-mineshaft-100">Projects</h3> <h3 className="text-lg font-semibold text-mineshaft-100">Projects</h3>
{userId !== membership.user.id && ( {userId !== membership.user.id && Boolean(membership.user.publicKey) && (
<IconButton <IconButton
ariaLabel="copy icon" ariaLabel="copy icon"
variant="plain" variant="plain"