feat: Add conditional API key display for auth and auto-login (#8684)
* ✨ Add IS_AUTO_LOGIN constant to handle auto login feature in NodeInputField and TableNodeCellRender components 🔧 Add loginLangflow utility function to facilitate login process in tests * ✨ (NodeInputField/index.tsx): introduce useIsAutoLogin hook to simplify logic for determining auto login status ✨ (tableNodeCellRender/index.tsx): introduce useIsAutoLogin hook to simplify logic for determining auto login status 📝 (use-is-auto-login.ts): add custom hook useIsAutoLogin to encapsulate logic for determining auto login status
This commit is contained in:
parent
797a7b6848
commit
0895ebbdcb
5 changed files with 131 additions and 6 deletions
|
|
@ -6,6 +6,7 @@ import {
|
|||
CustomParameterLabel,
|
||||
getCustomParameterTitle,
|
||||
} from "@/customization/components/custom-parameter";
|
||||
import { useIsAutoLogin } from "@/hooks/use-is-auto-login";
|
||||
import useAuthStore from "@/stores/authStore";
|
||||
import { cn } from "@/utils/utils";
|
||||
import { useEffect, useMemo, useRef } from "react";
|
||||
|
|
@ -16,6 +17,7 @@ import {
|
|||
DEFAULT_TOOLSET_PLACEHOLDER,
|
||||
FLEX_VIEW_TYPES,
|
||||
ICON_STROKE_WIDTH,
|
||||
IS_AUTO_LOGIN,
|
||||
LANGFLOW_SUPPORTED_TYPES,
|
||||
} from "../../../../constants/constants";
|
||||
import useFlowStore from "../../../../stores/flowStore";
|
||||
|
|
@ -44,13 +46,17 @@ export default function NodeInputField({
|
|||
isToolMode = false,
|
||||
}: NodeInputFieldComponentType): JSX.Element {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const isAuth = useAuthStore((state) => state.isAuthenticated);
|
||||
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
|
||||
const isAutoLogin = useIsAutoLogin();
|
||||
const shouldDisplayApiKey = isAuthenticated && !isAutoLogin;
|
||||
|
||||
const { currentFlowId, currentFlowName } = useFlowStore(
|
||||
useShallow((state) => ({
|
||||
currentFlowId: state.currentFlow?.id,
|
||||
currentFlowName: state.currentFlow?.name,
|
||||
})),
|
||||
);
|
||||
|
||||
const myData = useTypesStore((state) => state.data);
|
||||
const postTemplateValue = usePostTemplateValue({
|
||||
node: data.node!,
|
||||
|
|
@ -75,10 +81,10 @@ export default function NodeInputField({
|
|||
flowId: currentFlowId ?? "",
|
||||
nodeType: data?.type?.toLowerCase() ?? "",
|
||||
flowName: currentFlowName ?? "",
|
||||
isAuth,
|
||||
isAuth: shouldDisplayApiKey!,
|
||||
variableName: name,
|
||||
};
|
||||
}, [data?.node?.id, isAuth, name]);
|
||||
}, [data?.node?.id, shouldDisplayApiKey, name]);
|
||||
|
||||
useFetchDataOnMount(
|
||||
data.node!,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ import useHandleOnNewValue from "@/CustomNodes/hooks/use-handle-new-value";
|
|||
import useHandleNodeClass from "@/CustomNodes/hooks/use-handle-node-class";
|
||||
import { ParameterRenderComponent } from "@/components/core/parameterRenderComponent";
|
||||
import { NodeInfoType } from "@/components/core/parameterRenderComponent/types";
|
||||
import { IS_AUTO_LOGIN } from "@/constants/constants";
|
||||
import { useIsAutoLogin } from "@/hooks/use-is-auto-login";
|
||||
import useAuthStore from "@/stores/authStore";
|
||||
import useFlowStore from "@/stores/flowStore";
|
||||
import { APIClassType } from "@/types/api";
|
||||
|
|
@ -17,7 +19,9 @@ export default function TableNodeCellRender({
|
|||
const node = useFlowStore((state) => state.getNode(nodeId));
|
||||
const parameter = node?.data?.node?.template?.[parameterId];
|
||||
const currentFlow = useFlowStore((state) => state.currentFlow);
|
||||
const isAuth = useAuthStore((state) => state.isAuthenticated);
|
||||
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
|
||||
const isAutoLogin = useIsAutoLogin();
|
||||
const shouldDisplayApiKey = isAuthenticated && !isAutoLogin;
|
||||
|
||||
const disabled = isTargetHandleConnected(
|
||||
edges,
|
||||
|
|
@ -43,10 +47,10 @@ export default function TableNodeCellRender({
|
|||
flowId: currentFlow?.id ?? "",
|
||||
nodeType: node?.data?.type?.toLowerCase() ?? "",
|
||||
flowName: currentFlow?.name ?? "",
|
||||
isAuth,
|
||||
isAuth: shouldDisplayApiKey!,
|
||||
variableName: parameterId,
|
||||
};
|
||||
}, [nodeId, isAuth, parameterId]);
|
||||
}, [nodeId, shouldDisplayApiKey, parameterId]);
|
||||
|
||||
return (
|
||||
parameter && (
|
||||
|
|
|
|||
8
src/frontend/src/hooks/use-is-auto-login.ts
Normal file
8
src/frontend/src/hooks/use-is-auto-login.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import { IS_AUTO_LOGIN } from "@/constants/constants";
|
||||
import useAuthStore from "@/stores/authStore";
|
||||
|
||||
export const useIsAutoLogin = (): boolean => {
|
||||
const autoLogin = useAuthStore((state) => state.autoLogin);
|
||||
const isAutoLoginEnv = IS_AUTO_LOGIN;
|
||||
return autoLogin ?? isAutoLoginEnv;
|
||||
};
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import { adjustScreenView } from "../../utils/adjust-screen-view";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { extractAndCleanCode } from "../../utils/extract-and-clean-code";
|
||||
import { loginLangflow } from "../../utils/login-langflow";
|
||||
|
||||
test(
|
||||
"user must be able to see api key in webhook component when auto login is disabled",
|
||||
{ tag: ["@release"] },
|
||||
async ({ page }) => {
|
||||
await page.route("**/api/v1/auto_login", (route) => {
|
||||
route.fulfill({
|
||||
status: 500,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({
|
||||
detail: { auto_login: false },
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
await loginLangflow(page);
|
||||
|
||||
await awaitBootstrapTest(page, { skipGoto: true });
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
|
||||
await page.getByTestId("sidebar-search-input").fill("webhook");
|
||||
|
||||
await page.waitForSelector('[data-testid="dataWebhook"]', {
|
||||
timeout: 3000,
|
||||
});
|
||||
|
||||
await page
|
||||
.getByTestId("dataWebhook")
|
||||
.hover()
|
||||
.then(async () => {
|
||||
await page.getByTestId("add-component-button-webhook").click();
|
||||
});
|
||||
|
||||
await adjustScreenView(page);
|
||||
|
||||
await page.getByTestId("title-Webhook").click();
|
||||
|
||||
await page.getByTestId("edit-button-modal").click();
|
||||
|
||||
await page
|
||||
.getByTestId("button_open_text_area_modal_str_edit_curl_advanced")
|
||||
.click();
|
||||
|
||||
const curl = await page.getByTestId("text-area-modal").inputValue();
|
||||
|
||||
expect(curl).toContain("x-api-key");
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
"user must be able to not see api key in webhook component when auto login is enabled",
|
||||
{ tag: ["@release"] },
|
||||
async ({ page }) => {
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.waitForSelector('[data-testid="blank-flow"]', {
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.getByTestId("sidebar-search-input").click();
|
||||
|
||||
await page.getByTestId("sidebar-search-input").fill("webhook");
|
||||
|
||||
await page.waitForSelector('[data-testid="dataWebhook"]', {
|
||||
timeout: 3000,
|
||||
});
|
||||
|
||||
await page
|
||||
.getByTestId("dataWebhook")
|
||||
.hover()
|
||||
.then(async () => {
|
||||
await page.getByTestId("add-component-button-webhook").click();
|
||||
});
|
||||
|
||||
await adjustScreenView(page);
|
||||
|
||||
await page.getByTestId("title-Webhook").click();
|
||||
|
||||
await page.getByTestId("edit-button-modal").click();
|
||||
|
||||
await page
|
||||
.getByTestId("button_open_text_area_modal_str_edit_curl_advanced")
|
||||
.click();
|
||||
|
||||
const curl = await page.getByTestId("text-area-modal").inputValue();
|
||||
|
||||
expect(curl).not.toContain("x-api-key");
|
||||
},
|
||||
);
|
||||
8
src/frontend/tests/utils/login-langflow.ts
Normal file
8
src/frontend/tests/utils/login-langflow.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import { Page } from "playwright/test";
|
||||
|
||||
export const loginLangflow = async (page: Page) => {
|
||||
await page.goto("/");
|
||||
await page.getByPlaceholder("Username").fill("langflow");
|
||||
await page.getByPlaceholder("Password").fill("langflow");
|
||||
await page.getByRole("button", { name: "Sign In" }).click();
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue