Update ST V3 to machine identity

This commit is contained in:
Tuan Dang
2023-11-24 19:19:31 +07:00
parent 41c41a647f
commit 595a26a366
71 changed files with 651 additions and 697 deletions
@@ -4,15 +4,14 @@ import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context";
import { withPermission } from "@app/hoc";
import {
OrgMachineIdentityTab,
OrgMembersTab,
OrgRoleTabSection,
OrgServiceTokenTab
} from "./components";
OrgRoleTabSection} from "./components";
enum TabSections {
Member = "members",
Roles = "roles",
ServiceTokens = "service-tokens"
MachineIdentities = "machine-identities"
}
export const MembersPage = withPermission(
@@ -26,14 +25,14 @@ export const MembersPage = withPermission(
<Tabs defaultValue={TabSections.Member}>
<TabList>
<Tab value={TabSections.Member}>People</Tab>
<Tab value={TabSections.ServiceTokens}>Machine Identities</Tab>
<Tab value={TabSections.MachineIdentities}>Machine Identities</Tab>
<Tab value={TabSections.Roles}>Roles</Tab>
</TabList>
<TabPanel value={TabSections.Member}>
<OrgMembersTab />
</TabPanel>
<TabPanel value={TabSections.ServiceTokens}>
<OrgServiceTokenTab />
<TabPanel value={TabSections.MachineIdentities}>
<OrgMachineIdentityTab />
</TabPanel>
<TabPanel value={TabSections.Roles}>
<OrgRoleTabSection />
@@ -1,8 +1,8 @@
import { motion } from "framer-motion";
import { ServiceTokenV3Section } from "./components";
import { MachineIdentitySection } from "./components";
export const OrgServiceTokenTab = () => {
export const OrgMachineIdentityTab = () => {
return (
<motion.div
key="panel-service-token"
@@ -11,7 +11,7 @@ export const OrgServiceTokenTab = () => {
animate={{ opacity: 1, translateX: 0 }}
exit={{ opacity: 0, translateX: 30 }}
>
<ServiceTokenV3Section />
<MachineIdentitySection />
</motion.div>
);
}
@@ -28,9 +28,9 @@ import {
} from "@app/context";
import { useToggle } from "@app/hooks";
import {
useCreateServiceTokenV3,
useCreateMachineIdentity,
useGetRoles,
useUpdateServiceTokenV3
useUpdateMachineIdentity
} from "@app/hooks/api";
import { ServiceTokenV3TrustedIp } from "@app/hooks/api/serviceTokens/types";
import { UsePopUpState } from "@app/hooks/usePopUp";
@@ -79,16 +79,17 @@ const schema = yup.object({
export type FormData = yup.InferType<typeof schema>;
type Props = {
popUp: UsePopUpState<["serviceTokenV3", "upgradePlan"]>;
popUp: UsePopUpState<["machineIdentity", "upgradePlan"]>;
handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void;
handlePopUpToggle: (popUpName: keyof UsePopUpState<["serviceTokenV3", "upgradePlan"]>, state?: boolean) => void;
handlePopUpToggle: (popUpName: keyof UsePopUpState<["machineIdentity", "upgradePlan"]>, state?: boolean) => void;
};
export const AddServiceTokenV3Modal = ({
export const AddMachineIdentityModal = ({
popUp,
handlePopUpOpen,
handlePopUpToggle
}: Props) => {
const { createNotification } = useNotificationContext();
const [newServiceTokenJSON, setNewServiceTokenJSON] = useState("");
const [isServiceTokenJSONCopied, setIsServiceTokenJSONCopied] = useToggle(false);
@@ -101,9 +102,9 @@ export const AddServiceTokenV3Modal = ({
orgId
});
const { mutateAsync: createMutateAsync } = useCreateServiceTokenV3();
const { mutateAsync: updateMutateAsync } = useUpdateServiceTokenV3();
const { createNotification } = useNotificationContext();
const { mutateAsync: createMutateAsync } = useCreateMachineIdentity();
const { mutateAsync: updateMutateAsync } = useUpdateMachineIdentity();
const {
control,
handleSubmit,
@@ -136,8 +137,9 @@ export const AddServiceTokenV3Modal = ({
};
useEffect(() => {
const serviceTokenData = popUp?.serviceTokenV3?.data as {
serviceTokenDataId: string;
const machineIdentity = popUp?.machineIdentity?.data as {
machineId: string;
name: string;
role: string;
customRole: {
@@ -148,15 +150,15 @@ export const AddServiceTokenV3Modal = ({
accessTokenTTL: number;
isRefreshTokenRotationEnabled: boolean;
};
if (!roles?.length) return;
if (serviceTokenData) {
if (machineIdentity) {
reset({
name: serviceTokenData.name,
name: machineIdentity.name,
expiresIn: "",
role: serviceTokenData?.customRole?.slug ?? serviceTokenData.role,
trustedIps: serviceTokenData.trustedIps.map(({
role: machineIdentity?.customRole?.slug ?? machineIdentity.role,
trustedIps: machineIdentity.trustedIps.map(({
ipAddress,
prefix
}: ServiceTokenV3TrustedIp) => {
@@ -164,8 +166,8 @@ export const AddServiceTokenV3Modal = ({
ipAddress: `${ipAddress}${prefix !== undefined ? `/${prefix}` : ""}`
});
}),
accessTokenTTL: String(serviceTokenData.accessTokenTTL),
isRefreshTokenRotationEnabled: serviceTokenData.isRefreshTokenRotationEnabled
accessTokenTTL: String(machineIdentity.accessTokenTTL),
isRefreshTokenRotationEnabled: machineIdentity.isRefreshTokenRotationEnabled
});
} else {
reset({
@@ -178,7 +180,7 @@ export const AddServiceTokenV3Modal = ({
}]
});
}
}, [popUp?.serviceTokenV3?.data, roles]);
}, [popUp?.machineIdentity?.data, roles]);
const { fields: tokenTrustedIps, append: appendTrustedIp, remove: removeTrustedIp } = useFieldArray({ control, name: "trustedIps" });
@@ -192,17 +194,17 @@ export const AddServiceTokenV3Modal = ({
}: FormData) => {
try {
const serviceTokenData = popUp?.serviceTokenV3?.data as {
serviceTokenDataId: string;
const machineIdentity = popUp?.machineIdentity?.data as {
machineId: string;
name: string;
role: string;
};
if (serviceTokenData) {
if (machineIdentity) {
// update
await updateMutateAsync({
serviceTokenDataId: serviceTokenData.serviceTokenDataId,
machineId: machineIdentity.machineId,
name,
role,
trustedIps,
@@ -211,7 +213,7 @@ export const AddServiceTokenV3Modal = ({
isRefreshTokenRotationEnabled
});
handlePopUpToggle("serviceTokenV3", false);
handlePopUpToggle("machineIdentity", false);
} else {
const { refreshToken } = await createMutateAsync({
@@ -228,7 +230,7 @@ export const AddServiceTokenV3Modal = ({
}
createNotification({
text: `Successfully ${popUp?.serviceTokenV3?.data ? "updated" : "created"} service account`,
text: `Successfully ${popUp?.machineIdentity?.data ? "updated" : "created"} machine identity`,
type: "success"
});
@@ -236,7 +238,7 @@ export const AddServiceTokenV3Modal = ({
} catch (err) {
console.error(err);
createNotification({
text: `Failed to ${popUp?.serviceTokenV3?.data ? "updated" : "created"} service account`,
text: `Failed to ${popUp?.machineIdentity?.data ? "updated" : "created"} machine identity`,
type: "error"
});
}
@@ -246,14 +248,14 @@ export const AddServiceTokenV3Modal = ({
return (
<Modal
isOpen={popUp?.serviceTokenV3?.isOpen}
isOpen={popUp?.machineIdentity?.isOpen}
onOpenChange={(isOpen) => {
handlePopUpToggle("serviceTokenV3", isOpen);
handlePopUpToggle("machineIdentity", isOpen);
reset();
setNewServiceTokenJSON("");
}}
>
<ModalContent title={`${popUp?.serviceTokenV3?.data ? "Update" : "Create"} Service Account`}>
<ModalContent title={`${popUp?.machineIdentity?.data ? "Update" : "Create"} Machine Identity`}>
{!hasServiceTokenJSON ? (
<form onSubmit={handleSubmit(onFormSubmit)}>
<Tabs defaultValue={TabSections.General}>
@@ -283,7 +285,7 @@ export const AddServiceTokenV3Modal = ({
>
<Input
{...field}
placeholder="My ST V3"
placeholder="Machine 1"
/>
</FormControl>
)}
@@ -294,7 +296,7 @@ export const AddServiceTokenV3Modal = ({
defaultValue=""
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
<FormControl
label={`${popUp?.serviceTokenV3?.data ? "Update" : ""} Role`}
label={`${popUp?.machineIdentity?.data ? "Update" : ""} Role`}
errorText={error?.message}
isError={Boolean(error)}
className="mt-4"
@@ -325,7 +327,7 @@ export const AddServiceTokenV3Modal = ({
defaultValue=""
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
<FormControl
label={`${popUp?.serviceTokenV3?.data ? "Update" : ""} Refresh Token Expires In`}
label={`${popUp?.machineIdentity?.data ? "Update" : ""} Refresh Token Expires In`}
errorText={error?.message}
isError={Boolean(error)}
className="mt-4"
@@ -457,12 +459,12 @@ export const AddServiceTokenV3Modal = ({
isLoading={isSubmitting}
isDisabled={isSubmitting}
>
{popUp?.serviceTokenV3?.data ? "Update" : "Create"}
{popUp?.machineIdentity?.data ? "Update" : "Create"}
</Button>
<Button
colorSchema="secondary"
variant="plain"
onClick={() => handlePopUpToggle("serviceTokenV3", false)}
onClick={() => handlePopUpToggle("machineIdentity", false)}
>
Cancel
</Button>
@@ -9,35 +9,33 @@ import {
} from "@app/components/v2";
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context";
import { withPermission } from "@app/hoc";
import {
useDeleteServiceTokenV3
} from "@app/hooks/api";
import { useDeleteMachineIdentity } from "@app/hooks/api";
import { usePopUp } from "@app/hooks/usePopUp";
import { AddServiceTokenV3Modal } from "./AddServiceTokenV3Modal";
import { ServiceTokenV3Table } from "./ServiceTokenV3Table";
import { AddMachineIdentityModal } from "./AddMachineIdentityModal";
import { MachineIdentityTable } from "./MachineIdentityTable";
export const ServiceTokenV3Section = withPermission(
export const MachineIdentitySection = withPermission(
() => {
const { createNotification } = useNotificationContext();
const { mutateAsync: deleteMutateAsync } = useDeleteServiceTokenV3();
const { mutateAsync: deleteMutateAsync } = useDeleteMachineIdentity();
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
"serviceTokenV3",
"deleteServiceTokenV3",
"machineIdentity",
"deleteMachineIdentity",
"upgradePlan"
] as const);
const onDeleteServiceTokenDataSubmit = async (serviceTokenDataId: string) => {
const onDeleteMachineIdentitySubmit = async (machineId: string) => {
try {
await deleteMutateAsync({
serviceTokenDataId
machineId
});
createNotification({
text: "Successfully deleted service token v3",
type: "success"
});
handlePopUpClose("deleteServiceTokenV3");
handlePopUpClose("deleteMachineIdentity");
} catch (err) {
console.error(err);
createNotification({
@@ -51,7 +49,7 @@ export const ServiceTokenV3Section = withPermission(
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex justify-between mb-8">
<p className="text-xl font-semibold text-mineshaft-100">
Machines
Machine Identities (MIs)
</p>
<OrgPermissionCan
I={OrgPermissionActions.Create}
@@ -62,32 +60,32 @@ export const ServiceTokenV3Section = withPermission(
colorSchema="secondary"
type="submit"
leftIcon={<FontAwesomeIcon icon={faPlus} />}
onClick={() => handlePopUpOpen("serviceTokenV3")}
onClick={() => handlePopUpOpen("machineIdentity")}
isDisabled={!isAllowed}
>
Create account
Create MI
</Button>
)}
</OrgPermissionCan>
</div>
<ServiceTokenV3Table
<MachineIdentityTable
handlePopUpOpen={handlePopUpOpen}
/>
<AddServiceTokenV3Modal
<AddMachineIdentityModal
popUp={popUp}
handlePopUpOpen={handlePopUpOpen}
handlePopUpToggle={handlePopUpToggle}
/>
<DeleteActionModal
isOpen={popUp.deleteServiceTokenV3.isOpen}
isOpen={popUp.deleteMachineIdentity.isOpen}
title={`Are you sure want to delete ${
(popUp?.deleteServiceTokenV3?.data as { name: string })?.name || ""
(popUp?.deleteMachineIdentity?.data as { name: string })?.name || ""
}?`}
onChange={(isOpen) => handlePopUpToggle("deleteServiceTokenV3", isOpen)}
onChange={(isOpen) => handlePopUpToggle("deleteMachineIdentity", isOpen)}
deleteKey="confirm"
onDeleteApproved={() =>
onDeleteServiceTokenDataSubmit(
(popUp?.deleteServiceTokenV3?.data as { serviceTokenDataId: string })?.serviceTokenDataId
onDeleteMachineIdentitySubmit(
(popUp?.deleteMachineIdentity?.data as { machineId: string })?.machineId
)
}
/>
@@ -24,17 +24,18 @@ import {
OrgPermissionSubjects,
useOrganization} from "@app/context";
import {
useGetOrgServiceMemberships,
useGetMachineMembershipOrgs,
useGetRoles,
useUpdateServiceTokenV3} from "@app/hooks/api";
useUpdateMachineIdentity
} from "@app/hooks/api";
import { ServiceTokenV3TrustedIp } from "@app/hooks/api/serviceTokens/types"
import { UsePopUpState } from "@app/hooks/usePopUp";
type Props = {
handlePopUpOpen: (
popUpName: keyof UsePopUpState<["deleteServiceTokenV3", "serviceTokenV3"]>,
popUpName: keyof UsePopUpState<["deleteMachineIdentity", "machineIdentity"]>,
data?: {
serviceTokenDataId?: string;
machineId?: string;
name?: string;
role?: string;
customRole?: {
@@ -48,42 +49,42 @@ type Props = {
) => void;
};
export const ServiceTokenV3Table = ({
export const MachineIdentityTable = ({
handlePopUpOpen
}: Props) => {
const { createNotification } = useNotificationContext();
const { currentOrg } = useOrganization();
const orgId = currentOrg?._id || "";
const { mutateAsync: updateMutateAsync } = useUpdateServiceTokenV3();
const { data, isLoading } = useGetOrgServiceMemberships(currentOrg?._id || "");
const { mutateAsync: updateMutateAsync } = useUpdateMachineIdentity();
const { data, isLoading } = useGetMachineMembershipOrgs(currentOrg?._id || "");
const { data: roles } = useGetRoles({
orgId
});
const handleChangeRole = async ({
serviceTokenDataId,
machineId,
role
}: {
serviceTokenDataId: string;
machineId: string;
role: string;
}) => {
try {
await updateMutateAsync({
serviceTokenDataId,
machineId,
role
});
createNotification({
text: "Successfully updated service account role",
text: "Successfully updated machine identity role",
type: "success"
});
} catch (err) {
console.error(err);
createNotification({
text: "Failed to update service account role",
text: "Failed to update machine identity role",
type: "error"
});
}
@@ -138,12 +139,12 @@ export const ServiceTokenV3Table = ({
</Tr>
</THead>
<TBody>
{isLoading && <TableSkeleton columns={7} innerKey="service-tokens" />}
{isLoading && <TableSkeleton columns={7} innerKey="org-machine-identities" />}
{!isLoading &&
data &&
data.length > 0 &&
data.map(({
service: {
machineIdentity: {
_id,
name,
// isActive,
@@ -195,7 +196,7 @@ export const ServiceTokenV3Table = ({
dropdownContainerClassName="border border-mineshaft-600 bg-mineshaft-800"
onValueChange={(selectedRole) =>
handleChangeRole({
serviceTokenDataId: _id,
machineId: _id,
role: selectedRole
})
}
@@ -235,8 +236,8 @@ export const ServiceTokenV3Table = ({
{(isAllowed) => (
<IconButton
onClick={async () => {
handlePopUpOpen("serviceTokenV3", {
serviceTokenDataId: _id,
handlePopUpOpen("machineIdentity", {
machineId: _id,
name,
role,
customRole,
@@ -262,8 +263,8 @@ export const ServiceTokenV3Table = ({
{(isAllowed) => (
<IconButton
onClick={() => {
handlePopUpOpen("deleteServiceTokenV3", {
serviceTokenDataId: _id,
handlePopUpOpen("deleteMachineIdentity", {
machineId: _id,
name
});
}}
@@ -285,7 +286,7 @@ export const ServiceTokenV3Table = ({
{!isLoading && data && data?.length === 0 && (
<Tr>
<Td colSpan={7}>
<EmptyState title="No system users have been created in this organization" icon={faServer} />
<EmptyState title="No MIs have been created in this organization" icon={faServer} />
</Td>
</Tr>
)}
@@ -0,0 +1 @@
export { MachineIdentitySection } from "./MachineIdentitySection";
@@ -0,0 +1 @@
export { MachineIdentitySection } from "./MachineIdentitySection";
@@ -0,0 +1 @@
export { OrgMachineIdentityTab } from "./OrgMachineIdentityTab";
@@ -118,7 +118,7 @@ export const OrgMembersTable = ({
}
}
const isLoading = isMembersLoading || IsWsMembershipLoading || isRolesLoading;
const isLoading = isMembersLoading || isRolesLoading;
const isIamOwner = useMemo(
() => members?.find(({ user: u }) => userId === u?._id)?.role === "owner",
@@ -1 +0,0 @@
export { ServiceTokenV3Section } from "./ServiceTokenV3Section";
@@ -1 +0,0 @@
export { ServiceTokenV3Section } from "./ServiceTokenV3Section";
@@ -1 +0,0 @@
export { OrgServiceTokenTab } from "./OrgServiceTokenTab";
@@ -1,3 +1,3 @@
export { OrgMachineIdentityTab } from "./OrgMachineIdentityTab";
export { OrgMembersTab } from "./OrgMembersTab";
export { OrgRoleTabSection } from "./OrgRoleTabSection";
export { OrgServiceTokenTab } from "./OrgServiceTokenTab";
export { OrgRoleTabSection } from "./OrgRoleTabSection";