From 5609af53b0c32f7005bf17ebf98bb5ada2ca49c8 Mon Sep 17 00:00:00 2001 From: RAHEEL Date: Fri, 4 Oct 2024 20:34:31 +0500 Subject: [PATCH 1/5] set api_url for npm packages --- client/packages/lowcoder/src/constants/npmPlugins.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/client/packages/lowcoder/src/constants/npmPlugins.ts b/client/packages/lowcoder/src/constants/npmPlugins.ts index 58cb098f5..0e094b622 100644 --- a/client/packages/lowcoder/src/constants/npmPlugins.ts +++ b/client/packages/lowcoder/src/constants/npmPlugins.ts @@ -1,3 +1,7 @@ -export const SERVER_HOST = `${REACT_APP_NODE_SERVICE_URL ?? ""}`; -export const NPM_REGISTRY_URL = `${SERVER_HOST}/node-service/api/npm/registry`; -export const NPM_PLUGIN_ASSETS_BASE_URL = `${SERVER_HOST}/node-service/api/npm/package`; +// export const SERVER_HOST = `${REACT_APP_NODE_SERVICE_URL ?? ""}`; +// export const NPM_REGISTRY_URL = `${SERVER_HOST}/node-service/api/npm/registry`; +// export const NPM_PLUGIN_ASSETS_BASE_URL = `${SERVER_HOST}/node-service/api/npm/package`; + +export const SERVER_HOST = `${REACT_APP_API_SERVICE_URL ?? ""}`; +export const NPM_REGISTRY_URL = `${SERVER_HOST}/api/npm/registry`; +export const NPM_PLUGIN_ASSETS_BASE_URL = `${SERVER_HOST}/api/npm/package`; \ No newline at end of file From a9f94b2bf9d4e00733b8e08e15017a33e9e2cecc Mon Sep 17 00:00:00 2001 From: Thomasr Date: Fri, 4 Oct 2024 14:20:29 -0400 Subject: [PATCH 2/5] Fixed /api/npm/package/* endpoint response type --- .../api/npm/PrivateNpmRegistryController.java | 13 ++++++++----- .../api/npm/PrivateNpmRegistryEndpoint.java | 4 ++-- server/node-service/src/controllers/npm.ts | 6 +++--- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryController.java b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryController.java index 4f66cbf4a..115cde35c 100644 --- a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryController.java +++ b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryController.java @@ -40,20 +40,23 @@ public Mono> getNpmPackageAsset(String path) { @NotNull private Mono> forwardToNodeService(String path, String prefix) { + String withoutLeadingSlash = path.startsWith("/") ? path.substring(1) : path; return sessionUserService.getVisitorOrgMemberCache().flatMap(orgMember -> organizationService.getOrgCommonSettings(orgMember.getOrgId()).flatMap(organizationCommonSettings -> { Map config = Map.of("npmRegistries", organizationCommonSettings.get("npmRegistries"), "workspaceId", orgMember.getOrgId()); return WebClientBuildHelper.builder() .systemProxy() .build() .post() - .uri(nodeServerHelper.createUri(prefix + "/" + path)) + .uri(nodeServerHelper.createUri(prefix + "/" + withoutLeadingSlash)) .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromValue(config)) .retrieve().toEntity(Resource.class) - .map(response -> ResponseEntity - .status(response.getStatusCode()) - .headers(response.getHeaders()) - .body(response.getBody())); + .map(response -> { + return ResponseEntity + .status(response.getStatusCode()) + .headers(response.getHeaders()) + .body(response.getBody()); + }); })); } } diff --git a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryEndpoint.java b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryEndpoint.java index 33cfc758f..51dc79591 100644 --- a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryEndpoint.java +++ b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryEndpoint.java @@ -21,7 +21,7 @@ public interface PrivateNpmRegistryEndpoint { summary = "Get NPM registry Metadata", description = "Retrieve the metadata of private NPM registry package." ) -// @GetMapping("/registry/{name}") + @GetMapping("/registry/{name}") public Mono> getNpmPackageMeta(@PathVariable String name); @Operation( @@ -30,6 +30,6 @@ public interface PrivateNpmRegistryEndpoint { summary = "Get NPM registry asset", description = "Retrieve the asset of private NPM registry package." ) -// @GetMapping("/package/{path}") + @GetMapping("/package/{*path}") public Mono> getNpmPackageAsset(@PathVariable String path); } diff --git a/server/node-service/src/controllers/npm.ts b/server/node-service/src/controllers/npm.ts index 83fb2bd6b..b89b6da4c 100644 --- a/server/node-service/src/controllers/npm.ts +++ b/server/node-service/src/controllers/npm.ts @@ -3,7 +3,7 @@ import fs from "fs/promises"; import { spawn } from "child_process"; import { Request as ServerRequest, Response as ServerResponse } from "express"; import { NpmRegistryService, NpmRegistryConfigEntry, NpmRegistryConfig } from "../services/npmRegistry"; - +import {default as pathlib} from 'path'; type RequestConfig = { workspaceId: string; @@ -217,7 +217,7 @@ async function fetchPackageFileInner(request: ServerRequest, response: ServerRes logger.info(`Fetching tarball: ${tarball}`); await fetchAndUnpackTarball(tarball, packageId, packageVersion, registry, baseDir); } catch (error) { - logger.error(`Error fetching package: ${error} ${(error as {stack: string}).stack}`); + logger.error(`Error fetching package: ${error} ${(error as any)?.stack}`); return response.status(500).send("Internal server error"); } finally { PackageProcessingQueue.resolve(packageId); @@ -232,7 +232,7 @@ async function fetchPackageFileInner(request: ServerRequest, response: ServerRes return response.sendFile(`${packageBaseDir}/index.mjs`); } - return response.sendFile(`${packageBaseDir}/${file}`); + return response.sendFile(pathlib.resolve(`${packageBaseDir}/${file}`)); } catch (error) { logger.error(`Error fetching package file: ${error} ${(error as {stack: string})?.stack?.toString()}`); response.status(500).send("Internal server error"); From 5c37d58f2a3f423d8e448ef528aeddedeb71a606 Mon Sep 17 00:00:00 2001 From: Thomasr Date: Tue, 8 Oct 2024 11:19:25 -0400 Subject: [PATCH 3/5] add applicationid param to private npm repository endpoint --- .../api/npm/PrivateNpmRegistryController.java | 18 +++++++++++------- .../api/npm/PrivateNpmRegistryEndpoint.java | 8 ++++---- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryController.java b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryController.java index 115cde35c..70ff12e07 100644 --- a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryController.java +++ b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryController.java @@ -3,6 +3,8 @@ import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; import org.lowcoder.api.home.SessionUserService; +import org.lowcoder.domain.application.service.ApplicationServiceImpl; +import org.lowcoder.domain.organization.service.OrgMemberServiceImpl; import org.lowcoder.domain.organization.service.OrganizationService; import org.lowcoder.infra.constant.NewUrl; import org.lowcoder.infra.js.NodeServerHelper; @@ -27,22 +29,24 @@ public class PrivateNpmRegistryController implements PrivateNpmRegistryEndpoint{ private static final String NPM_REGISTRY_METADATA = "npm/registry"; private static final String NPM_REGISTRY_ASSET = "npm/package"; + private final OrgMemberServiceImpl orgMemberServiceImpl; + private final ApplicationServiceImpl applicationServiceImpl; @Override - public Mono> getNpmPackageMeta(String name) { - return forwardToNodeService(name, NPM_REGISTRY_METADATA); + public Mono> getNpmPackageMeta(String applicationId, String name) { + return forwardToNodeService(applicationId, name, NPM_REGISTRY_METADATA); } @Override - public Mono> getNpmPackageAsset(String path) { - return forwardToNodeService(path, NPM_REGISTRY_ASSET); + public Mono> getNpmPackageAsset(String applicationId, String path) { + return forwardToNodeService(applicationId, path, NPM_REGISTRY_ASSET); } @NotNull - private Mono> forwardToNodeService(String path, String prefix) { + private Mono> forwardToNodeService(String applicationId, String path, String prefix) { String withoutLeadingSlash = path.startsWith("/") ? path.substring(1) : path; - return sessionUserService.getVisitorOrgMemberCache().flatMap(orgMember -> organizationService.getOrgCommonSettings(orgMember.getOrgId()).flatMap(organizationCommonSettings -> { - Map config = Map.of("npmRegistries", organizationCommonSettings.get("npmRegistries"), "workspaceId", orgMember.getOrgId()); + return applicationServiceImpl.findById(applicationId).flatMap(application -> organizationService.getById(application.getOrganizationId())).flatMap(orgMember -> organizationService.getOrgCommonSettings(orgMember.getId()).flatMap(organizationCommonSettings -> { + Map config = Map.of("npmRegistries", organizationCommonSettings.get("npmRegistries"), "workspaceId", orgMember.getId()); return WebClientBuildHelper.builder() .systemProxy() .build() diff --git a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryEndpoint.java b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryEndpoint.java index 51dc79591..77a5982cd 100644 --- a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryEndpoint.java +++ b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryEndpoint.java @@ -21,8 +21,8 @@ public interface PrivateNpmRegistryEndpoint { summary = "Get NPM registry Metadata", description = "Retrieve the metadata of private NPM registry package." ) - @GetMapping("/registry/{name}") - public Mono> getNpmPackageMeta(@PathVariable String name); + @GetMapping("/registry/{applicationId}/{name}") + public Mono> getNpmPackageMeta(@PathVariable String applicationId, @PathVariable String name); @Operation( tags = TAG_NPM_REGISTRY_MANAGEMENT, @@ -30,6 +30,6 @@ public interface PrivateNpmRegistryEndpoint { summary = "Get NPM registry asset", description = "Retrieve the asset of private NPM registry package." ) - @GetMapping("/package/{*path}") - public Mono> getNpmPackageAsset(@PathVariable String path); + @GetMapping("/package/{applicationId}/{*path}") + public Mono> getNpmPackageAsset(@PathVariable String applicationId, @PathVariable String path); } From 79f8f03ea247b7d20dfe9a28d23018e14b4d4fae Mon Sep 17 00:00:00 2001 From: RAHEEL Date: Tue, 8 Oct 2024 21:37:05 +0500 Subject: [PATCH 4/5] send appId in registry/package endpoints --- .../lowcoder/src/comps/comps/remoteComp/loaders.tsx | 9 ++++++--- .../src/comps/comps/remoteComp/remoteComp.tsx | 12 +++++++----- client/packages/lowcoder/src/comps/utils/remote.ts | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/client/packages/lowcoder/src/comps/comps/remoteComp/loaders.tsx b/client/packages/lowcoder/src/comps/comps/remoteComp/loaders.tsx index 1f15cff05..9fa889eb0 100644 --- a/client/packages/lowcoder/src/comps/comps/remoteComp/loaders.tsx +++ b/client/packages/lowcoder/src/comps/comps/remoteComp/loaders.tsx @@ -8,13 +8,16 @@ import { } from "types/remoteComp"; async function npmLoader( - remoteInfo: RemoteCompInfo + { + appId, + ...remoteInfo + }: RemoteCompInfo & {appId?: string} ): Promise { // Falk: removed "packageVersion = "latest" as default value fir packageVersion - to ensure no automatic version jumping. const localPackageVersion = remoteInfo.packageVersion || "latest"; const { packageName, packageVersion, compName } = remoteInfo; - const entry = `${NPM_PLUGIN_ASSETS_BASE_URL}/${packageName}@${localPackageVersion}/index.js`; + const entry = `${NPM_PLUGIN_ASSETS_BASE_URL}/${appId}/${packageName}@${localPackageVersion}/index.js`; try { const module = await import( @@ -51,7 +54,7 @@ async function bundleLoader( return comp; } -export const loaders: Record = { +export const loaders: Record> = { npm: npmLoader, bundle: bundleLoader, }; diff --git a/client/packages/lowcoder/src/comps/comps/remoteComp/remoteComp.tsx b/client/packages/lowcoder/src/comps/comps/remoteComp/remoteComp.tsx index e9989f7ac..da29dda9f 100644 --- a/client/packages/lowcoder/src/comps/comps/remoteComp/remoteComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/remoteComp/remoteComp.tsx @@ -16,6 +16,7 @@ import { CompContext } from "@lowcoder-ee/comps/utils/compContext"; import React from "react"; import type { AppState } from "@lowcoder-ee/redux/reducers"; import { useSelector } from "react-redux"; +import { useApplicationId } from "@lowcoder-ee/util/hooks"; const ViewError = styled.div` display: flex; @@ -51,7 +52,7 @@ interface RemoteCompReadyAction { interface RemoteCompViewProps { isLowcoderComp?: boolean; - loadComp: (packageVersion?: string) => Promise; + loadComp: (packageVersion?: string, appId?: string) => Promise; loadingElement?: () => React.ReactNode; errorElement?: (error: any) => React.ReactNode; source?: RemoteCompSource; @@ -62,6 +63,7 @@ const RemoteCompView = React.memo((props: React.PropsWithChildren(""); const editorState = useContext(EditorContext); const compState = useContext(CompContext); + const appId = useApplicationId(); const lowcoderCompPackageVersion = editorState?.getAppSettings().lowcoderCompVersion || 'latest'; const latestLowcoderCompsVersion = useSelector((state: AppState) => state.npmPlugin.packageVersion['lowcoder-comps']); @@ -79,7 +81,7 @@ const RemoteCompView = React.memo((props: React.PropsWithChildren { setError(""); - loadComp(packageVersion).catch((e) => { + loadComp(packageVersion, appId).catch((e) => { setError(String(e)); }); }); @@ -117,7 +119,7 @@ export function remoteComp( this.compValue = params.value; } - private async load(packageVersion = 'latest') { + private async load(packageVersion = 'latest', appId = 'none') { if (!remoteInfo) { return; } @@ -129,7 +131,7 @@ export function remoteComp( log.error("loader not found, remote info:", remoteInfo); return; } - const RemoteExportedComp = await finalLoader({...remoteInfo, packageVersion}); + const RemoteExportedComp = await finalLoader({...remoteInfo, packageVersion, appId}); if (!RemoteExportedComp) { return; } @@ -159,7 +161,7 @@ export function remoteComp( this.load(packageVersion)} + loadComp={(packageVersion?: string, appId?: string) => this.load(packageVersion, appId)} loadingElement={loadingElement} source={remoteInfo?.source} /> diff --git a/client/packages/lowcoder/src/comps/utils/remote.ts b/client/packages/lowcoder/src/comps/utils/remote.ts index 5d9d8f603..c0984d5d0 100644 --- a/client/packages/lowcoder/src/comps/utils/remote.ts +++ b/client/packages/lowcoder/src/comps/utils/remote.ts @@ -39,7 +39,7 @@ export function parseCompType(compType: string) { } export async function getNpmPackageMeta(packageName: string) { - const res = await axios.get(`${NPM_REGISTRY_URL}/${packageName}`); + const res = await axios.get(`${NPM_REGISTRY_URL}/none/${packageName}`); if (res.status >= 400) { return null; } From a839beb2b1ad1ce1dc9549b81386d4caed71f020 Mon Sep 17 00:00:00 2001 From: Thomasr Date: Tue, 8 Oct 2024 15:25:53 -0400 Subject: [PATCH 5/5] enable anonymous api --- .../framework/security/SecurityConfig.java | 1 + .../api/npm/PrivateNpmRegistryController.java | 55 +++++++++++++------ 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/framework/security/SecurityConfig.java b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/framework/security/SecurityConfig.java index f09e615a9..75c253134 100644 --- a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/framework/security/SecurityConfig.java +++ b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/framework/security/SecurityConfig.java @@ -145,6 +145,7 @@ SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, NewUrl.ORGANIZATION_URL + "/*/datasourceTypes"), // datasource types ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, NewUrl.ORGANIZATION_URL + "/byuser/*"), ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, NewUrl.DATASOURCE_URL + "/jsDatasourcePlugins"), + ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, NewUrl.NPM_REGISTRY + "/**"), ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, "/api/docs/**") ) .permitAll() diff --git a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryController.java b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryController.java index 70ff12e07..61ce28053 100644 --- a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryController.java +++ b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/npm/PrivateNpmRegistryController.java @@ -44,23 +44,44 @@ public Mono> getNpmPackageAsset(String applicationId, S @NotNull private Mono> forwardToNodeService(String applicationId, String path, String prefix) { + String withoutLeadingSlash = path.startsWith("/") ? path.substring(1) : path; - return applicationServiceImpl.findById(applicationId).flatMap(application -> organizationService.getById(application.getOrganizationId())).flatMap(orgMember -> organizationService.getOrgCommonSettings(orgMember.getId()).flatMap(organizationCommonSettings -> { - Map config = Map.of("npmRegistries", organizationCommonSettings.get("npmRegistries"), "workspaceId", orgMember.getId()); - return WebClientBuildHelper.builder() - .systemProxy() - .build() - .post() - .uri(nodeServerHelper.createUri(prefix + "/" + withoutLeadingSlash)) - .contentType(MediaType.APPLICATION_JSON) - .body(BodyInserters.fromValue(config)) - .retrieve().toEntity(Resource.class) - .map(response -> { - return ResponseEntity - .status(response.getStatusCode()) - .headers(response.getHeaders()) - .body(response.getBody()); - }); - })); + if(applicationId.equals("none")) { + return sessionUserService.getVisitorOrgMemberCache().flatMap(orgMember -> organizationService.getOrgCommonSettings(orgMember.getOrgId()).flatMap(organizationCommonSettings -> { + Map config = Map.of("npmRegistries", organizationCommonSettings.get("npmRegistries"), "workspaceId", orgMember.getOrgId()); + return WebClientBuildHelper.builder() + .systemProxy() + .build() + .post() + .uri(nodeServerHelper.createUri(prefix + "/" + withoutLeadingSlash)) + .contentType(MediaType.APPLICATION_JSON) + .body(BodyInserters.fromValue(config)) + .retrieve().toEntity(Resource.class) + .map(response -> { + return ResponseEntity + .status(response.getStatusCode()) + .headers(response.getHeaders()) + .body(response.getBody()); + }); + })); + } else{ + return applicationServiceImpl.findById(applicationId).flatMap(application -> organizationService.getById(application.getOrganizationId())).flatMap(orgMember -> organizationService.getOrgCommonSettings(orgMember.getId()).flatMap(organizationCommonSettings -> { + Map config = Map.of("npmRegistries", organizationCommonSettings.get("npmRegistries"), "workspaceId", orgMember.getId()); + return WebClientBuildHelper.builder() + .systemProxy() + .build() + .post() + .uri(nodeServerHelper.createUri(prefix + "/" + withoutLeadingSlash)) + .contentType(MediaType.APPLICATION_JSON) + .body(BodyInserters.fromValue(config)) + .retrieve().toEntity(Resource.class) + .map(response -> { + return ResponseEntity + .status(response.getStatusCode()) + .headers(response.getHeaders()) + .body(response.getBody()); + }); + })); + } } }