From 9a4b2f7d81e89b881ce9f8dc79bb42094a7d2af9 Mon Sep 17 00:00:00 2001 From: Akhil Mohan Date: Mon, 11 Dec 2023 13:56:36 +0530 Subject: [PATCH] feat(infisical-pg): resolved type check issue and linted frontend --- .../AuditLogsPage/components/LogsTableRow.tsx | 6 +- .../AddServiceTokenV3Modal.tsx | 543 ------------------ .../ServiceTokenV3Table.tsx | 274 --------- 3 files changed, 3 insertions(+), 820 deletions(-) delete mode 100644 frontend/src/views/Project/MembersPage/components/ServiceTokenTab/components/ServiceTokenV3Section/AddServiceTokenV3Modal.tsx delete mode 100644 frontend/src/views/Project/MembersPage/components/ServiceTokenTab/components/ServiceTokenV3Section/ServiceTokenV3Table.tsx diff --git a/frontend/src/views/Project/AuditLogsPage/components/LogsTableRow.tsx b/frontend/src/views/Project/AuditLogsPage/components/LogsTableRow.tsx index 78f2f8245..7fc69400e 100644 --- a/frontend/src/views/Project/AuditLogsPage/components/LogsTableRow.tsx +++ b/frontend/src/views/Project/AuditLogsPage/components/LogsTableRow.tsx @@ -158,21 +158,21 @@ export const LogsTableRow = ({ auditLog }: Props) => {

{`Name: ${event.metadata.name}`}

); - case EventType.CREATEidENTITY: + case EventType.CREATE_IDENTITY: return (

{`ID: ${event.metadata.identityId}`}

{`Name: ${event.metadata.name}`}

); - case EventType.UPDATEidENTITY: + case EventType.UPDATE_IDENTITY: return (

{`ID: ${event.metadata.identityId}`}

{`Name: ${event.metadata.name}`}

); - case EventType.DELETEidENTITY: + case EventType.DELETE_IDENTITY: return (

{`ID: ${event.metadata.identityId}`}

diff --git a/frontend/src/views/Project/MembersPage/components/ServiceTokenTab/components/ServiceTokenV3Section/AddServiceTokenV3Modal.tsx b/frontend/src/views/Project/MembersPage/components/ServiceTokenTab/components/ServiceTokenV3Section/AddServiceTokenV3Modal.tsx deleted file mode 100644 index d52b42ecf..000000000 --- a/frontend/src/views/Project/MembersPage/components/ServiceTokenTab/components/ServiceTokenV3Section/AddServiceTokenV3Modal.tsx +++ /dev/null @@ -1,543 +0,0 @@ -import { useEffect, useState } from "react"; -import { Controller, useFieldArray, useForm } from "react-hook-form"; -import { faCheck, faCopy, faPlus, faXmark } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { yupResolver } from "@hookform/resolvers/yup"; -import { motion } from "framer-motion"; -import nacl from "tweetnacl"; -import { encodeBase64 } from "tweetnacl-util"; -import * as yup from "yup"; - -import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; -import { - decryptAssymmetric, - encryptAssymmetric -} from "@app/components/utilities/cryptography/crypto"; -import { - Button, - FormControl, - IconButton, - Input, - Modal, - ModalContent, - Select, - SelectItem, - Switch, - Tab, - TabList, - TabPanel, - Tabs, - UpgradePlanModal -} from "@app/components/v2"; -import { useOrganization, useSubscription, useWorkspace } from "@app/context"; -import { useToggle } from "@app/hooks"; -import { - useCreateServiceTokenV3, - useGetRoles, - useGetUserWsKey, - useUpdateServiceTokenV3 -} from "@app/hooks/api"; -import { ServiceTokenV3TrustedIp } from "@app/hooks/api/serviceTokens/types"; -import { UsePopUpState } from "@app/hooks/usePopUp"; - -enum TabSections { - General = "general", - Advanced = "advanced" -} - -const expirations = [ - { label: "Never", value: "" }, - { label: "1 day", value: "86400" }, - { label: "7 days", value: "604800" }, - { label: "1 month", value: "2592000" }, - { label: "6 months", value: "15552000" }, - { label: "12 months", value: "31104000" } -]; - -const schema = yup - .object({ - name: yup.string().required("ST V3 name is required"), - expiresIn: yup.string(), - accessTokenTTL: yup - .string() - .test("is-positive-integer", "Access Token TTL must be a positive integer", (value) => { - if (typeof value === "undefined") { - return false; - } - - const num = parseInt(value, 10); - return !Number.isNaN(num) && num > 0 && String(num) === value; - }) - .required("Access Token TTL is required"), - role: yup.string().required("ST V3 role is required"), - trustedIps: yup - .array( - yup.object({ - ipAddress: yup.string().max(50).required().label("IP Address") - }) - ) - .min(1) - .required() - .label("Trusted IP"), - isRefreshTokenRotationEnabled: yup.boolean().default(false) - }) - .required(); - -export type FormData = yup.InferType; - -type Props = { - popUp: UsePopUpState<["serviceTokenV3", "upgradePlan"]>; - handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void; - handlePopUpToggle: ( - popUpName: keyof UsePopUpState<["serviceTokenV3", "upgradePlan"]>, - state?: boolean - ) => void; -}; - -export const AddServiceTokenV3Modal = ({ popUp, handlePopUpOpen, handlePopUpToggle }: Props) => { - const [newServiceTokenJSON, setNewServiceTokenJSON] = useState(""); - const [isServiceTokenJSONCopied, setIsServiceTokenJSONCopied] = useToggle(false); - - const { subscription } = useSubscription(); - const { currentOrg } = useOrganization(); - const { currentWorkspace } = useWorkspace(); - - const orgId = currentOrg?.id || ""; - const workspaceId = currentWorkspace?.id || ""; - - const { data: roles } = useGetRoles({ - orgId, - workspaceId - }); - - const { data: latestFileKey } = useGetUserWsKey(workspaceId); - const { mutateAsync: createMutateAsync } = useCreateServiceTokenV3(); - const { mutateAsync: updateMutateAsync } = useUpdateServiceTokenV3(); - const { createNotification } = useNotificationContext(); - const { - control, - handleSubmit, - reset, - formState: { isSubmitting } - } = useForm({ - resolver: yupResolver(schema), - defaultValues: { - name: "", - accessTokenTTL: "7200", - trustedIps: [ - { - ipAddress: "0.0.0.0/0" - } - ] - } - }); - - useEffect(() => { - let timer: NodeJS.Timeout; - - if (isServiceTokenJSONCopied) { - timer = setTimeout(() => setIsServiceTokenJSONCopied.off(), 2000); - } - - return () => clearTimeout(timer); - }, [setIsServiceTokenJSONCopied]); - - const copyTokenToClipboard = () => { - navigator.clipboard.writeText(newServiceTokenJSON); - setIsServiceTokenJSONCopied.on(); - }; - - useEffect(() => { - const serviceTokenData = popUp?.serviceTokenV3?.data as { - serviceTokenDataId: string; - name: string; - role: string; - customRole: { - name: string; - slug: string; - }; - trustedIps: ServiceTokenV3TrustedIp[]; - accessTokenTTL: number; - isRefreshTokenRotationEnabled: boolean; - }; - - if (!roles?.length) return; - - if (serviceTokenData) { - reset({ - name: serviceTokenData.name, - role: serviceTokenData?.customRole?.slug ?? serviceTokenData.role, - trustedIps: serviceTokenData.trustedIps.map( - ({ ipAddress, prefix }: ServiceTokenV3TrustedIp) => { - return { - ipAddress: `${ipAddress}${prefix !== undefined ? `/${prefix}` : ""}` - }; - } - ), - accessTokenTTL: String(serviceTokenData.accessTokenTTL), - isRefreshTokenRotationEnabled: serviceTokenData.isRefreshTokenRotationEnabled - }); - } else { - reset({ - name: "", - accessTokenTTL: "7200", - role: roles[0].slug, - trustedIps: [ - { - ipAddress: "0.0.0.0/0" - } - ] - }); - } - }, [popUp?.serviceTokenV3?.data, roles]); - - const { - fields: tokenTrustedIps, - append: appendTrustedIp, - remove: removeTrustedIp - } = useFieldArray({ control, name: "trustedIps" }); - - const onFormSubmit = async ({ - name, - expiresIn, - accessTokenTTL, - role, - trustedIps, - isRefreshTokenRotationEnabled - }: FormData) => { - try { - const serviceTokenData = popUp?.serviceTokenV3?.data as { - serviceTokenDataId: string; - name: string; - role: string; - }; - - if (serviceTokenData) { - // update - - await updateMutateAsync({ - serviceTokenDataId: serviceTokenData.serviceTokenDataId, - name, - role, - trustedIps, - expiresIn: expiresIn === "" ? undefined : Number(expiresIn), - accessTokenTTL: Number(accessTokenTTL), - isRefreshTokenRotationEnabled - }); - - handlePopUpToggle("serviceTokenV3", false); - } else { - // create - if (!workspaceId) return; - if (!latestFileKey) return; - - const pair = nacl.box.keyPair(); - const secretKeyUint8Array = pair.secretKey; - const publicKeyUint8Array = pair.publicKey; - const privateKey = encodeBase64(secretKeyUint8Array); - const publicKey = encodeBase64(publicKeyUint8Array); - - const key = decryptAssymmetric({ - ciphertext: latestFileKey.encryptedKey, - nonce: latestFileKey.nonce, - publicKey: latestFileKey.sender.publicKey, - privateKey: localStorage.getItem("PRIVATE_KEY") as string - }); - - const { ciphertext, nonce } = encryptAssymmetric({ - plaintext: key, - publicKey, - privateKey: localStorage.getItem("PRIVATE_KEY") as string - }); - - const { refreshToken } = await createMutateAsync({ - name, - role, - workspaceId, - publicKey, - trustedIps, - expiresIn: expiresIn === "" ? undefined : Number(expiresIn), - accessTokenTTL: Number(accessTokenTTL), - encryptedKey: ciphertext, - nonce, - isRefreshTokenRotationEnabled - }); - - const downloadData = { - public_key: publicKey, - private_key: privateKey, - refresh_token: refreshToken - }; - - const serviceTokenJSON = JSON.stringify(downloadData, null, 2); - setNewServiceTokenJSON(serviceTokenJSON); - - const blob = new Blob([serviceTokenJSON], { type: "application/json" }); - const href = URL.createObjectURL(blob); - const link = document.createElement("a"); - link.href = href; - link.download = `infisical_${name}.json`; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - } - - createNotification({ - text: `Successfully ${popUp?.serviceTokenV3?.data ? "updated" : "created"} ST V3`, - type: "success" - }); - - reset(); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to ${popUp?.serviceTokenV3?.data ? "updated" : "created"} ST V3`, - type: "error" - }); - } - }; - - const hasServiceTokenJSON = Boolean(newServiceTokenJSON); - - return ( - { - handlePopUpToggle("serviceTokenV3", isOpen); - reset(); - setNewServiceTokenJSON(""); - }} - > - - {!hasServiceTokenJSON ? ( -
- - -
- General - Advanced -
-
- - - ( - - - - )} - /> - ( - - - - )} - /> - ( - - - - )} - /> - - - -
- {tokenTrustedIps.map(({ id }, index) => ( -
- { - return ( - - { - if (subscription?.ipAllowlisting) { - field.onChange(e); - return; - } - - handlePopUpOpen("upgradePlan"); - }} - placeholder="123.456.789.0" - /> - - ); - }} - /> - { - if (subscription?.ipAllowlisting) { - removeTrustedIp(index); - return; - } - - handlePopUpOpen("upgradePlan"); - }} - size="lg" - colorSchema="danger" - variant="plain" - ariaLabel="update" - className="p-3" - > - - -
- ))} -
- -
- ( - - - - )} - /> -
- ( - onChange(isChecked)} - isChecked={value} - > - Refresh Token Rotation - - )} - /> -

- When enabled, as a result of exchanging a refresh token, a new refresh token - will be issued and the existing token will be invalidated. -

-
-
-
-
-
- - -
-
- ) : ( -
-

{newServiceTokenJSON}

- - - - Click to copy - - -
- )} - handlePopUpToggle("upgradePlan", isOpen)} - text="You can use IP allowlisting if you switch to Infisical's Pro plan." - /> -
-
- ); -}; diff --git a/frontend/src/views/Project/MembersPage/components/ServiceTokenTab/components/ServiceTokenV3Section/ServiceTokenV3Table.tsx b/frontend/src/views/Project/MembersPage/components/ServiceTokenTab/components/ServiceTokenV3Section/ServiceTokenV3Table.tsx deleted file mode 100644 index 4057d3f1d..000000000 --- a/frontend/src/views/Project/MembersPage/components/ServiceTokenTab/components/ServiceTokenV3Section/ServiceTokenV3Table.tsx +++ /dev/null @@ -1,274 +0,0 @@ -import { faKey, faPencil, faXmark } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { format } from "date-fns"; - -import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; -import { ProjectPermissionCan } from "@app/components/permissions"; -import { - EmptyState, - IconButton, - Switch, - Table, - TableContainer, - TableSkeleton, - TBody, - Td, - Th, - THead, - Tr -} from "@app/components/v2"; -import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context"; -import { useGetWorkspaceServiceTokenDataV3, useUpdateServiceTokenV3 } 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"]>, - data?: { - serviceTokenDataId?: string; - name?: string; - role?: string; - customRole?: { - name: string; - slug: string; - }; - trustedIps?: ServiceTokenV3TrustedIp[]; - accessTokenTTL?: number; - isRefreshTokenRotationEnabled?: boolean; - } - ) => void; -}; - -export const ServiceTokenV3Table = ({ - handlePopUpOpen -}: Props) => { - const { createNotification } = useNotificationContext(); - const { currentWorkspace } = useWorkspace(); - const { data, isLoading } = useGetWorkspaceServiceTokenDataV3(currentWorkspace?.id || ""); - const { mutateAsync: updateMutateAsync } = useUpdateServiceTokenV3(); - - const handleToggleServiceTokenDataStatus = async ({ - serviceTokenDataId, - isActive - }: { - serviceTokenDataId: string; - isActive: boolean; - }) => { - try { - await updateMutateAsync({ - serviceTokenDataId, - isActive - }); - - createNotification({ - text: `Successfully ${isActive ? "enabled" : "disabled"} service token v3`, - type: "success" - }); - } catch (err) { - console.log(err); - createNotification({ - text: `Failed to ${isActive ? "enable" : "disable"} service token v3`, - type: "error" - }); - } - - return ( - - - - - - - - - - - - - - - {isLoading && } - {!isLoading && - data && - data.length > 0 && - data.map(({ - id, - name, - isActive, - role, - customRole, - trustedIps, - createdAt, - expiresAt, - accessTokenTTL, - isRefreshTokenRotationEnabled - }) => { - return ( - - - - - - - - - - - ); - })} - - - - - - - ); - } - )} - {!isLoading && data && data?.length === 0 && ( - - - - )} - -
NameStatusRoleTrusted IPsAccess Token TTLCreated AtValid Until -
{name} - - {(isAllowed) => ( - handleToggleServiceTokenDataStatus({ - serviceTokenDataId: id, - isActive: value - })} - isChecked={isActive} - isDisabled={!isAllowed} - > -

{isActive ? "Active" : "Inactive"}

-
- )} -
-
{customRole?.slug ?? role} - {trustedIps.map(({ - id: trustedIpId, - ipAddress, - prefix - }) => { - return ( -

- {`${ipAddress}${prefix !== undefined ? `/${prefix}` : ""}`} -

- ); - })} -
{accessTokenTTL}{format(new Date(createdAt), "yyyy-MM-dd")}{expiresAt ? format(new Date(expiresAt), "yyyy-MM-dd") : "-"} - - {(isAllowed) => ( - { - handlePopUpOpen("serviceTokenV3", { - serviceTokenDataId: id, - name, - role, - customRole, - trustedIps, - accessTokenTTL, - isRefreshTokenRotationEnabled - }); - }} - size="lg" - colorSchema="primary" - variant="plain" - ariaLabel="update" - isDisabled={!isAllowed} - > - - - )} - - - {(isAllowed) => ( - { - handlePopUpOpen("deleteServiceTokenV3", { - serviceTokenDataId: id, - name - }); - }} - size="lg" - colorSchema="danger" - variant="plain" - ariaLabel="update" - className="ml-4" - isDisabled={!isAllowed} - > - - - )} - -
{accessTokenTTL}{format(new Date(createdAt), "yyyy-MM-dd")}{expiresAt ? format(new Date(expiresAt), "yyyy-MM-dd") : "-"} - - {(isAllowed) => ( - { - handlePopUpOpen("serviceTokenV3", { - serviceTokenDataId: id, - name, - role, - customRole, - trustedIps, - accessTokenTTL, - isRefreshTokenRotationEnabled - }); - }} - size="lg" - colorSchema="primary" - variant="plain" - ariaLabel="update" - isDisabled={!isAllowed} - > - - - )} - - - {(isAllowed) => ( - { - handlePopUpOpen("deleteServiceTokenV3", { - serviceTokenDataId: id, - name - }); - }} - size="lg" - colorSchema="danger" - variant="plain" - ariaLabel="update" - className="ml-4" - isDisabled={!isAllowed} - > - - - )} - -
- -
-
- ); -};