This is an automated email from the ASF dual-hosted git repository.
fantonangeli pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-tools.git
The following commit(s) were added to refs/heads/main by this push:
new 5ebd85c3518 kie-issues#2466: Serverless Logic Web Tools: Runtime Tools
settings doesn't validate the data index url. (#2608)
5ebd85c3518 is described below
commit 5ebd85c351864ab86fb16714b34b5e996b3e7829
Author: Kumar Aditya Raj <[email protected]>
AuthorDate: Tue Oct 15 15:28:00 2024 +0530
kie-issues#2466: Serverless Logic Web Tools: Runtime Tools settings doesn't
validate the data index url. (#2608)
---
.../src/gatewayApi/apis.tsx | 19 +++++++
.../serverless-logic-web-tools/src/i18n/AppI18n.ts | 6 +++
.../src/i18n/locales/de.ts | 6 +++
.../src/i18n/locales/en.ts | 6 +++
.../settings/runtimeTools/RuntimeToolsSettings.tsx | 58 ++++++++++++++++++++--
.../serverless-logic-web-tools/src/url/index.ts | 9 ++++
.../url/dataIndexValidUrl.test.ts} | 21 ++++----
.../src/context/AppContextProvider.tsx | 3 +-
.../sonataflow-deployment-webapp/src/data/index.ts | 19 -------
9 files changed, 115 insertions(+), 32 deletions(-)
diff --git a/packages/runtime-tools-swf-gateway-api/src/gatewayApi/apis.tsx
b/packages/runtime-tools-swf-gateway-api/src/gatewayApi/apis.tsx
index 619ebe387c0..3d391590079 100644
--- a/packages/runtime-tools-swf-gateway-api/src/gatewayApi/apis.tsx
+++ b/packages/runtime-tools-swf-gateway-api/src/gatewayApi/apis.tsx
@@ -729,3 +729,22 @@ export const saveFormContent = (formName: string, content:
FormContent): Promise
.catch((error) => reject(error));
});
};
+
+export async function verifyDataIndex(dataIndexUrl?: string): Promise<boolean>
{
+ if (!dataIndexUrl) {
+ return false;
+ }
+
+ try {
+ const response = await fetch(dataIndexUrl, {
+ headers: {
+ "Content-Type": "application/json",
+ },
+ method: "POST",
+ body: '{"query":""}',
+ });
+ return response.status === 200;
+ } catch (e) {
+ return false;
+ }
+}
diff --git a/packages/serverless-logic-web-tools/src/i18n/AppI18n.ts
b/packages/serverless-logic-web-tools/src/i18n/AppI18n.ts
index 9824c624c08..3b1178924cc 100644
--- a/packages/serverless-logic-web-tools/src/i18n/AppI18n.ts
+++ b/packages/serverless-logic-web-tools/src/i18n/AppI18n.ts
@@ -105,6 +105,12 @@ interface AppDictionary extends ReferenceDictionary {
dependencyWarningTooltip: string;
};
};
+ RuntimeToolsSettings: {
+ configModal: {
+ validDataIndexURLError: string;
+ dataIndexConnectionError: string;
+ };
+ };
}
export interface AppI18n extends AppDictionary, CommonI18n {}
diff --git a/packages/serverless-logic-web-tools/src/i18n/locales/de.ts
b/packages/serverless-logic-web-tools/src/i18n/locales/de.ts
index f795fce6748..2c102f9781b 100644
--- a/packages/serverless-logic-web-tools/src/i18n/locales/de.ts
+++ b/packages/serverless-logic-web-tools/src/i18n/locales/de.ts
@@ -112,4 +112,10 @@ export const de: AppI18n = {
"Modelle in diesem Arbeitsbereich können von Bereitstellungen aus
anderen Arbeitsbereichen abhängen.",
},
},
+ RuntimeToolsSettings: {
+ configModal: {
+ validDataIndexURLError: "Bitte geben Sie eine gültige Datenindex-URL
ein.",
+ dataIndexConnectionError: "Verbindung abgelehnt. Bitte überprüfen Sie
die bereitgestellten Informationen.",
+ },
+ },
};
diff --git a/packages/serverless-logic-web-tools/src/i18n/locales/en.ts
b/packages/serverless-logic-web-tools/src/i18n/locales/en.ts
index 800745e2565..cb2359064e1 100644
--- a/packages/serverless-logic-web-tools/src/i18n/locales/en.ts
+++ b/packages/serverless-logic-web-tools/src/i18n/locales/en.ts
@@ -108,4 +108,10 @@ export const en: AppI18n = {
dependencyWarningTooltip: "Models in this workspace may depend on
deployments from other workspaces.",
},
},
+ RuntimeToolsSettings: {
+ configModal: {
+ validDataIndexURLError: "Please enter a valid Data Index URL.",
+ dataIndexConnectionError: "Connection refused. Please check the
information provided.",
+ },
+ },
};
diff --git
a/packages/serverless-logic-web-tools/src/settings/runtimeTools/RuntimeToolsSettings.tsx
b/packages/serverless-logic-web-tools/src/settings/runtimeTools/RuntimeToolsSettings.tsx
index ccbdd84723c..79b253567e4 100644
---
a/packages/serverless-logic-web-tools/src/settings/runtimeTools/RuntimeToolsSettings.tsx
+++
b/packages/serverless-logic-web-tools/src/settings/runtimeTools/RuntimeToolsSettings.tsx
@@ -17,10 +17,10 @@
* under the License.
*/
-import React from "react";
+import React, { useEffect } from "react";
import { Button, ButtonVariant } from
"@patternfly/react-core/dist/js/components/Button";
import { EmptyState, EmptyStateBody, EmptyStateIcon } from
"@patternfly/react-core/dist/js/components/EmptyState";
-import { ActionGroup, Form, FormGroup } from
"@patternfly/react-core/dist/js/components/Form";
+import { ActionGroup, Form, FormAlert, FormGroup } from
"@patternfly/react-core/dist/js/components/Form";
import { InputGroup, InputGroupText } from
"@patternfly/react-core/dist/js/components/InputGroup";
import { Modal, ModalVariant } from
"@patternfly/react-core/dist/js/components/Modal";
import { PageSection } from "@patternfly/react-core/dist/js/components/Page";
@@ -43,14 +43,31 @@ import {
saveConfigCookie,
} from "./RuntimeToolsConfig";
import { removeTrailingSlashFromUrl } from "../../url";
+import { isDataIndexUrlValid } from "../../url";
+import { Alert } from "@patternfly/react-core/dist/js";
+import { useAppI18n } from "../../i18n";
+import { verifyDataIndex } from
"@kie-tools/runtime-tools-swf-gateway-api/src/gatewayApi/apis";
const PAGE_TITLE = "Runtime Tools";
+enum FormValiationOptions {
+ INITIAL = "INITIAL",
+ INVALID = "INVALID",
+ CONNECTION_ERROR = "CONNECTION_ERROR",
+}
+
export function RuntimeToolsSettings(props: SettingsPageProps) {
+ const { i18n } = useAppI18n();
const settings = useSettings();
const settingsDispatch = useSettingsDispatch();
const [config, setConfig] = useState(settings.runtimeTools.config);
const [isModalOpen, setIsModalOpen] = useState(false);
+ const [isConfigValidated, setConfigValidated] =
useState(FormValiationOptions.INITIAL);
+ const [dataIndexUrlAvailable, setDataIndexUrlAvailable] =
useState<boolean>(false);
+
+ useEffect(() => {
+ setConfigValidated(FormValiationOptions.INITIAL);
+ }, [config]);
const handleModalToggle = useCallback(() => {
setIsModalOpen((prevIsModalOpen) => !prevIsModalOpen);
@@ -76,10 +93,23 @@ export function RuntimeToolsSettings(props:
SettingsPageProps) {
resetConfigCookie();
}, [settingsDispatch.runtimeTools]);
- const onApply = useCallback(() => {
+ const onApply = useCallback(async () => {
const newConfig: RuntimeToolsSettingsConfig = {
dataIndexUrl: removeTrailingSlashFromUrl(config.dataIndexUrl),
};
+ const isDataIndexUrlVerified = await verifyDataIndex(config.dataIndexUrl);
+ if (!isDataIndexUrlValid(config.dataIndexUrl)) {
+ setConfigValidated(FormValiationOptions.INVALID);
+ return;
+ } else {
+ if (isDataIndexUrlVerified == true) {
+ setDataIndexUrlAvailable(true);
+ } else {
+ setConfigValidated(FormValiationOptions.CONNECTION_ERROR);
+ return;
+ }
+ }
+
setConfig(newConfig);
settingsDispatch.runtimeTools.setConfig(newConfig);
saveConfigCookie(newConfig);
@@ -144,6 +174,28 @@ export function RuntimeToolsSettings(props:
SettingsPageProps) {
appendTo={props.pageContainerRef.current || document.body}
>
<Form>
+ {isConfigValidated === FormValiationOptions.INVALID && (
+ <FormAlert>
+ <Alert
+ variant="danger"
+
title={i18n.RuntimeToolsSettings.configModal.validDataIndexURLError}
+ aria-live="polite"
+ isInline
+ data-testid="alert-data-index-url-invalid"
+ />
+ </FormAlert>
+ )}
+ {isConfigValidated === FormValiationOptions.CONNECTION_ERROR && (
+ <FormAlert>
+ <Alert
+ variant="danger"
+
title={i18n.RuntimeToolsSettings.configModal.dataIndexConnectionError}
+ aria-live="polite"
+ isInline
+ data-testid="alert-data-index-url-connection-error"
+ />
+ </FormAlert>
+ )}
<FormGroup
label={"Data Index URL"}
labelIcon={
diff --git a/packages/serverless-logic-web-tools/src/url/index.ts
b/packages/serverless-logic-web-tools/src/url/index.ts
index be6c6a1b06e..a9a65557128 100644
--- a/packages/serverless-logic-web-tools/src/url/index.ts
+++ b/packages/serverless-logic-web-tools/src/url/index.ts
@@ -26,3 +26,12 @@
export function removeTrailingSlashFromUrl(url: string): string {
return url.replace(/\/$/, "");
}
+
+export function isDataIndexUrlValid(url: string): boolean {
+ try {
+ const parsedUrl = new URL(url);
+ return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:";
+ } catch (_) {
+ return false;
+ }
+}
diff --git a/packages/serverless-logic-web-tools/src/url/index.ts
b/packages/serverless-logic-web-tools/tests/url/dataIndexValidUrl.test.ts
similarity index 66%
copy from packages/serverless-logic-web-tools/src/url/index.ts
copy to packages/serverless-logic-web-tools/tests/url/dataIndexValidUrl.test.ts
index be6c6a1b06e..2b67d22ef20 100644
--- a/packages/serverless-logic-web-tools/src/url/index.ts
+++ b/packages/serverless-logic-web-tools/tests/url/dataIndexValidUrl.test.ts
@@ -17,12 +17,15 @@
* under the License.
*/
-/**
- * Remove the trailing slash from an URL if it exists.
- *
- * @param url -
- * @returns
- */
-export function removeTrailingSlashFromUrl(url: string): string {
- return url.replace(/\/$/, "");
-}
+import { isDataIndexUrlValid } from "../../src/url";
+
+describe("isDataIndexUrlValid", () => {
+ it.each([
+ ["http://example.com", true],
+ ["http://example.com/", true],
+ ["https://example.com/", true],
+ ["ftps://example.com/", false],
+ ])("the data index URL %s validation should be %s", (inputUrl, isValidUrl)
=> {
+ expect(isDataIndexUrlValid(inputUrl)).toBe(isValidUrl);
+ });
+});
diff --git
a/packages/sonataflow-deployment-webapp/src/context/AppContextProvider.tsx
b/packages/sonataflow-deployment-webapp/src/context/AppContextProvider.tsx
index d9e645f007c..f8f8822fc28 100644
--- a/packages/sonataflow-deployment-webapp/src/context/AppContextProvider.tsx
+++ b/packages/sonataflow-deployment-webapp/src/context/AppContextProvider.tsx
@@ -19,9 +19,10 @@
import React, { PropsWithChildren, useEffect, useMemo, useState } from "react";
import { DEFAULT_APPDATA_VALUES } from "../AppConstants";
-import { AppData, verifyDataIndex } from "../data";
+import { AppData } from "../data";
import { useAppDataPromise } from "../hooks/useAppDataPromise";
import { AppContext } from "./AppContext";
+import { verifyDataIndex } from
"@kie-tools/runtime-tools-swf-gateway-api/src/gatewayApi/apis";
export function AppContextProvider(props: PropsWithChildren<{}>) {
const appDataPromise = useAppDataPromise();
diff --git a/packages/sonataflow-deployment-webapp/src/data/index.ts
b/packages/sonataflow-deployment-webapp/src/data/index.ts
index 37aa2884108..505d6362ea9 100644
--- a/packages/sonataflow-deployment-webapp/src/data/index.ts
+++ b/packages/sonataflow-deployment-webapp/src/data/index.ts
@@ -29,22 +29,3 @@ export async function fetchAppData(): Promise<AppData> {
const response = await fetch(routes.dataJson.path({}));
return (await response.json()) as AppData;
}
-
-export async function verifyDataIndex(dataIndexUrl?: string): Promise<boolean>
{
- if (!dataIndexUrl) {
- return false;
- }
-
- try {
- const response = await fetch(dataIndexUrl, {
- headers: {
- "Content-Type": "application/json",
- },
- method: "POST",
- body: '{"query":""}',
- });
- return response.status === 200;
- } catch (e) {
- return false;
- }
-}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]