From 176d92546c40ad23e86c1a176bbe41519e76c4ac Mon Sep 17 00:00:00 2001 From: Tuan Dang Date: Fri, 3 Nov 2023 22:37:50 +0200 Subject: [PATCH] Split ST V3 modal into option tabs, re-modularized authn methods --- backend/src/helpers/secrets.ts | 2 +- backend/src/middleware/requireAuth.ts | 2 +- .../utils/authn/authDataExtractors/index.ts | 53 -- backend/src/utils/authn/authMode/index.ts | 4 - .../apiKey.ts | 0 .../apiKeyV2.ts | 0 .../utils/authn/authModeValidators/index.ts | 5 + .../{authMode => authModeValidators}/jwt.ts | 0 .../serviceTokenV2.ts | 0 .../serviceTokenV3.ts | 0 .../utils/authn/helpers/authDataExtractors.ts | 53 ++ .../{authMode/helpers.ts => helpers/index.ts} | 16 +- .../PersonalAPIKeyTab/PersonalAPIKeyTab.tsx | 4 +- .../ProjectServiceTokensTab.tsx | 4 +- .../AddServiceTokenV3Modal.tsx | 491 ++++++++++-------- 15 files changed, 336 insertions(+), 298 deletions(-) delete mode 100644 backend/src/utils/authn/authDataExtractors/index.ts delete mode 100644 backend/src/utils/authn/authMode/index.ts rename backend/src/utils/authn/{authMode => authModeValidators}/apiKey.ts (100%) rename backend/src/utils/authn/{authMode => authModeValidators}/apiKeyV2.ts (100%) create mode 100644 backend/src/utils/authn/authModeValidators/index.ts rename backend/src/utils/authn/{authMode => authModeValidators}/jwt.ts (100%) rename backend/src/utils/authn/{authMode => authModeValidators}/serviceTokenV2.ts (100%) rename backend/src/utils/authn/{authMode => authModeValidators}/serviceTokenV3.ts (100%) create mode 100644 backend/src/utils/authn/helpers/authDataExtractors.ts rename backend/src/utils/authn/{authMode/helpers.ts => helpers/index.ts} (95%) diff --git a/backend/src/helpers/secrets.ts b/backend/src/helpers/secrets.ts index beacf709d..f6252d5c6 100644 --- a/backend/src/helpers/secrets.ts +++ b/backend/src/helpers/secrets.ts @@ -49,7 +49,7 @@ import { import { TelemetryService } from "../services"; import { client, getEncryptionKey, getRootEncryptionKey } from "../config"; import { EEAuditLogService, EELogService, EESecretService } from "../ee/services"; -import { getAuthDataPayloadIdObj, getAuthDataPayloadUserObj } from "../utils/authn/authDataExtractors"; +import { getAuthDataPayloadIdObj, getAuthDataPayloadUserObj } from "../utils/authn/helpers"; import { getFolderByPath, getFolderIdFromServiceToken } from "../services/FolderService"; import picomatch from "picomatch"; import path from "path"; diff --git a/backend/src/middleware/requireAuth.ts b/backend/src/middleware/requireAuth.ts index 87672feb9..929d22fea 100644 --- a/backend/src/middleware/requireAuth.ts +++ b/backend/src/middleware/requireAuth.ts @@ -2,7 +2,7 @@ import jwt from "jsonwebtoken"; import { NextFunction, Request, Response } from "express"; import { AuthMode } from "../variables"; import { AuthData } from "../interfaces/middleware"; -import { extractAuthMode, getAuthData } from "../utils/authn/authMode"; +import { extractAuthMode, getAuthData } from "../utils/authn/helpers"; import { UnauthorizedRequestError } from "../utils/errors"; declare module "jsonwebtoken" { diff --git a/backend/src/utils/authn/authDataExtractors/index.ts b/backend/src/utils/authn/authDataExtractors/index.ts deleted file mode 100644 index 89c1f419e..000000000 --- a/backend/src/utils/authn/authDataExtractors/index.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { AuthData } from "../../../interfaces/middleware"; -import { - ServiceAccount, - ServiceTokenData, - ServiceTokenDataV3, - User -} from "../../../models"; - -/** - * Returns an object containing the id of the authentication data payload - * @param {AuthData} authData - authentication data object - * @returns - */ -export const getAuthDataPayloadIdObj = (authData: AuthData) => { - if (authData.authPayload instanceof User) { - return { userId: authData.authPayload._id }; - } - - if (authData.authPayload instanceof ServiceAccount) { - return { serviceAccountId: authData.authPayload._id }; - } - - if (authData.authPayload instanceof ServiceTokenData) { - return { serviceTokenDataId: authData.authPayload._id }; - } - - if (authData.authPayload instanceof ServiceTokenDataV3) { - return { serviceTokenDataId: authData.authPayload._id }; - } -}; - -/** - * Returns an object containing the user associated with the authentication data payload - * @param {AuthData} authData - authentication data object - * @returns - */ -export const getAuthDataPayloadUserObj = (authData: AuthData) => { - if (authData.authPayload instanceof User) { - return { user: authData.authPayload._id }; - } - - if (authData.authPayload instanceof ServiceAccount) { - return { user: authData.authPayload.user }; - } - - if (authData.authPayload instanceof ServiceTokenData) { - return { user: authData.authPayload.user }; - } - - if (authData.authPayload instanceof ServiceTokenDataV3) { - return { user: authData.authPayload.user }; - } -} \ No newline at end of file diff --git a/backend/src/utils/authn/authMode/index.ts b/backend/src/utils/authn/authMode/index.ts deleted file mode 100644 index 7d7262551..000000000 --- a/backend/src/utils/authn/authMode/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { - extractAuthMode, - getAuthData -} from "./helpers"; \ No newline at end of file diff --git a/backend/src/utils/authn/authMode/apiKey.ts b/backend/src/utils/authn/authModeValidators/apiKey.ts similarity index 100% rename from backend/src/utils/authn/authMode/apiKey.ts rename to backend/src/utils/authn/authModeValidators/apiKey.ts diff --git a/backend/src/utils/authn/authMode/apiKeyV2.ts b/backend/src/utils/authn/authModeValidators/apiKeyV2.ts similarity index 100% rename from backend/src/utils/authn/authMode/apiKeyV2.ts rename to backend/src/utils/authn/authModeValidators/apiKeyV2.ts diff --git a/backend/src/utils/authn/authModeValidators/index.ts b/backend/src/utils/authn/authModeValidators/index.ts new file mode 100644 index 000000000..0ac4c3c1c --- /dev/null +++ b/backend/src/utils/authn/authModeValidators/index.ts @@ -0,0 +1,5 @@ +export * from "./apiKey"; +export * from "./apiKeyV2"; +export * from "./jwt"; +export * from "./serviceTokenV2"; +export * from "./serviceTokenV3"; \ No newline at end of file diff --git a/backend/src/utils/authn/authMode/jwt.ts b/backend/src/utils/authn/authModeValidators/jwt.ts similarity index 100% rename from backend/src/utils/authn/authMode/jwt.ts rename to backend/src/utils/authn/authModeValidators/jwt.ts diff --git a/backend/src/utils/authn/authMode/serviceTokenV2.ts b/backend/src/utils/authn/authModeValidators/serviceTokenV2.ts similarity index 100% rename from backend/src/utils/authn/authMode/serviceTokenV2.ts rename to backend/src/utils/authn/authModeValidators/serviceTokenV2.ts diff --git a/backend/src/utils/authn/authMode/serviceTokenV3.ts b/backend/src/utils/authn/authModeValidators/serviceTokenV3.ts similarity index 100% rename from backend/src/utils/authn/authMode/serviceTokenV3.ts rename to backend/src/utils/authn/authModeValidators/serviceTokenV3.ts diff --git a/backend/src/utils/authn/helpers/authDataExtractors.ts b/backend/src/utils/authn/helpers/authDataExtractors.ts new file mode 100644 index 000000000..60639739e --- /dev/null +++ b/backend/src/utils/authn/helpers/authDataExtractors.ts @@ -0,0 +1,53 @@ +import { AuthData } from "../../../interfaces/middleware"; +import { + ServiceAccount, + ServiceTokenData, + ServiceTokenDataV3, + User +} from "../../../models"; + +/** + * Returns an object containing the id of the authentication data payload + * @param {AuthData} authData - authentication data object + * @returns + */ + export const getAuthDataPayloadIdObj = (authData: AuthData) => { + if (authData.authPayload instanceof User) { + return { userId: authData.authPayload._id }; + } + + if (authData.authPayload instanceof ServiceAccount) { + return { serviceAccountId: authData.authPayload._id }; + } + + if (authData.authPayload instanceof ServiceTokenData) { + return { serviceTokenDataId: authData.authPayload._id }; + } + + if (authData.authPayload instanceof ServiceTokenDataV3) { + return { serviceTokenDataId: authData.authPayload._id }; + } +}; + +/** + * Returns an object containing the user associated with the authentication data payload + * @param {AuthData} authData - authentication data object + * @returns + */ +export const getAuthDataPayloadUserObj = (authData: AuthData) => { + if (authData.authPayload instanceof User) { + return { user: authData.authPayload._id }; + } + + if (authData.authPayload instanceof ServiceAccount) { + return { user: authData.authPayload.user }; + } + + if (authData.authPayload instanceof ServiceTokenData) { + return { user: authData.authPayload.user }; + } + + if (authData.authPayload instanceof ServiceTokenDataV3) { + return { user: authData.authPayload.user }; + } +} \ No newline at end of file diff --git a/backend/src/utils/authn/authMode/helpers.ts b/backend/src/utils/authn/helpers/index.ts similarity index 95% rename from backend/src/utils/authn/authMode/helpers.ts rename to backend/src/utils/authn/helpers/index.ts index ecb852f61..064efe133 100644 --- a/backend/src/utils/authn/authMode/helpers.ts +++ b/backend/src/utils/authn/helpers/index.ts @@ -1,15 +1,19 @@ +import { AuthData } from "../../../interfaces/middleware"; import jwt from "jsonwebtoken"; import { getAuthSecret } from "../../../config"; import { ActorType } from "../../../ee/models"; import { AuthMode, AuthTokenType } from "../../../variables"; import { UnauthorizedRequestError } from "../../errors"; -import { validateAPIKey } from "./apiKey"; -import { validateAPIKeyV2 } from "./apiKeyV2"; -import { validateServiceTokenV2 } from "./serviceTokenV2"; -import { validateServiceTokenV3 } from "./serviceTokenV3"; -import { validateJWT } from "./jwt"; +import { + validateAPIKey, + validateAPIKeyV2, + validateJWT, + validateServiceTokenV2, + validateServiceTokenV3 +} from "../authModeValidators"; import { getUserAgentType } from "../../posthog"; -import { AuthData } from "../../../interfaces/middleware"; + +export * from "./authDataExtractors"; interface ExtractAuthModeParams { headers: { [key: string]: string | string[] | undefined } diff --git a/frontend/src/views/Settings/PersonalSettingsPage/PersonalAPIKeyTab/PersonalAPIKeyTab.tsx b/frontend/src/views/Settings/PersonalSettingsPage/PersonalAPIKeyTab/PersonalAPIKeyTab.tsx index 035f0b322..aba48b23e 100644 --- a/frontend/src/views/Settings/PersonalSettingsPage/PersonalAPIKeyTab/PersonalAPIKeyTab.tsx +++ b/frontend/src/views/Settings/PersonalSettingsPage/PersonalAPIKeyTab/PersonalAPIKeyTab.tsx @@ -1,10 +1,10 @@ import { APIKeySection } from "../APIKeySection"; -import { APIKeyV2Section } from "../APIKeyV2Section"; +// import { APIKeyV2Section } from "../APIKeyV2Section"; export const PersonalAPIKeyTab = () => { return ( <> - + {/* */} ); diff --git a/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectServiceTokensTab/ProjectServiceTokensTab.tsx b/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectServiceTokensTab/ProjectServiceTokensTab.tsx index 12312dc78..d4f8e79e7 100644 --- a/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectServiceTokensTab/ProjectServiceTokensTab.tsx +++ b/frontend/src/views/Settings/ProjectSettingsPage/components/ProjectServiceTokensTab/ProjectServiceTokensTab.tsx @@ -1,10 +1,10 @@ import { ServiceTokenSection } from "../ServiceTokenSection"; -import { ServiceTokenV3Section } from "../ServiceTokenV3Section"; +// import { ServiceTokenV3Section } from "../ServiceTokenV3Section"; export const ProjectServiceTokensTab = () => { return ( <> - + {/* */} ); diff --git a/frontend/src/views/Settings/ProjectSettingsPage/components/ServiceTokenV3Section/AddServiceTokenV3Modal.tsx b/frontend/src/views/Settings/ProjectSettingsPage/components/ServiceTokenV3Section/AddServiceTokenV3Modal.tsx index c1779b19e..3d76b2435 100644 --- a/frontend/src/views/Settings/ProjectSettingsPage/components/ServiceTokenV3Section/AddServiceTokenV3Modal.tsx +++ b/frontend/src/views/Settings/ProjectSettingsPage/components/ServiceTokenV3Section/AddServiceTokenV3Modal.tsx @@ -1,11 +1,13 @@ import { useEffect, useState } from "react"; import { Controller, useFieldArray, useForm } from "react-hook-form"; -import { faPlus, faXmark, faCheck, faCopy } from "@fortawesome/free-solid-svg-icons"; +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, @@ -21,8 +23,11 @@ import { Select, SelectItem, Switch, - UpgradePlanModal -} from "@app/components/v2"; + Tab, + TabList, + TabPanel, + Tabs, + UpgradePlanModal} from "@app/components/v2"; import { useSubscription, useWorkspace @@ -42,6 +47,11 @@ import { } 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" }, @@ -343,246 +353,269 @@ export const AddServiceTokenV3Modal = ({ {!hasServiceTokenJSON ? (
- ( - + +
+ General + Advanced +
+
+ + - -
- )} - /> - {tokenScopes.map(({ id }, index) => ( -
- ( - - - - )} - /> - ( - - - - )} - /> - ( - - - - )} - /> - remove(index)} - size="lg" - colorSchema="danger" - variant="plain" - ariaLabel="update" - className="p-3" - > - - -
- ))} -
- -
- {tokenTrustedIps.map(({ id }, index) => ( -
- { - return ( + ( { + {...field} + placeholder="My ST V3" + /> + + )} + /> + {tokenScopes.map(({ id }, index) => ( +
+ ( + + + + )} + /> + ( + + + + )} + /> + ( + + + + )} + /> + remove(index)} + size="lg" + colorSchema="danger" + variant="plain" + ariaLabel="update" + className="p-3" + > + + +
+ ))} +
+ +
+ ( + + + + )} + /> + + + +
+ {tokenTrustedIps.map(({ id }, index) => ( +
+ { + return ( + + { + if (subscription?.ipAllowlisting) { + field.onChange(e); + return; + } + + handlePopUpOpen("upgradePlan"); + }} + placeholder="123.456.789.0" + /> + + ); + }} + /> + { if (subscription?.ipAllowlisting) { - field.onChange(e); + removeTrustedIp(index); return; } handlePopUpOpen("upgradePlan"); }} - placeholder="123.456.789.0" + size="lg" + colorSchema="danger" + variant="plain" + ariaLabel="update" + className="p-3" + > + + +
+ ))} +
+ +
+ ( + + - ); - }} - /> - { - 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 - - )} - /> -
-
+ )} + /> +
+ ( + 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.

+
+
+
+ +