From 0f84de85898e134efac3dc7500e580e15c7da25c Mon Sep 17 00:00:00 2001 From: weareoutman Date: Thu, 9 Jan 2025 18:34:44 +0800 Subject: [PATCH] feat(): support block pages by license blacklist --- bricks/e2e/src/list-by-use-brick/index.tsx | 10 +-- etc/runtime.api.md | 5 +- packages/brick-container/package.json | 2 +- packages/easyops-runtime/package.json | 2 +- packages/easyops-runtime/src/auth-v2.ts | 10 ++- packages/easyops-runtime/src/auth.spec.ts | 62 +++++++++++++++++- packages/easyops-runtime/src/auth.ts | 37 +++++++++++ .../src/menu/fetchMenuById.spec.ts | 19 +++++- .../easyops-runtime/src/menu/fetchMenuById.ts | 55 ++++++++++------ .../easyops-runtime/src/menu/interfaces.ts | 4 +- packages/runtime/package.json | 2 +- .../runtime/src/internal/ErrorNode.spec.ts | 8 +-- packages/runtime/src/internal/ErrorNode.ts | 28 ++++---- packages/runtime/src/internal/Router.ts | 17 +++-- packages/runtime/src/internal/Runtime.spec.ts | 64 +++++++++++++++++++ packages/runtime/src/internal/Runtime.ts | 3 +- packages/runtime/src/internal/i18n.ts | 4 ++ yarn.lock | 10 +-- 18 files changed, 282 insertions(+), 60 deletions(-) diff --git a/bricks/e2e/src/list-by-use-brick/index.tsx b/bricks/e2e/src/list-by-use-brick/index.tsx index 3ee68cf3a5..4eddea0e42 100644 --- a/bricks/e2e/src/list-by-use-brick/index.tsx +++ b/bricks/e2e/src/list-by-use-brick/index.tsx @@ -1,8 +1,8 @@ import React from "react"; import { createDecorators } from "@next-core/element"; import { ReactNextElement } from "@next-core/react-element"; -import { ReactUseBrick } from "@next-core/react-runtime"; -import { UseSingleBrickConf } from "@next-core/types"; +import { ReactUseMultipleBricks } from "@next-core/react-runtime"; +import { UseBrickConf } from "@next-core/types"; const { defineElement, property } = createDecorators(); @@ -13,7 +13,7 @@ export }) class ListByUseBrick extends ReactNextElement { @property({ attribute: false }) - accessor useBrick: UseSingleBrickConf; + accessor useBrick: UseBrickConf; @property({ attribute: false }) accessor data: unknown; @@ -29,7 +29,7 @@ export function ListByUseBrickComponent({ useBrick, data, }: { - useBrick: UseSingleBrickConf; + useBrick: UseBrickConf; data: unknown; }) { if (!useBrick || !Array.isArray(data)) { @@ -38,7 +38,7 @@ export function ListByUseBrickComponent({ return ( <> {data.map((datum, index) => ( - + ))} ); diff --git a/etc/runtime.api.md b/etc/runtime.api.md index a13f1e9386..912fddd4da 100644 --- a/etc/runtime.api.md +++ b/etc/runtime.api.md @@ -348,7 +348,7 @@ export interface PageViewInfo { // (undocumented) path?: string; // (undocumented) - status: "ok" | "failed" | "redirected" | "not-found"; + status: "ok" | "failed" | "redirected" | "not-found" | "blocked"; } // @public (undocumented) @@ -441,6 +441,7 @@ export interface RuntimeHooks { isLoggedIn(): boolean; authenticate?(...args: unknown[]): unknown; logout?(...args: unknown[]): unknown; + isBlockedPath?(pathname: string): boolean; }; // (undocumented) checkInstalledApps?: { @@ -586,7 +587,7 @@ function updateTemplatePreviewSettings(appId: string, templateId: string, settin // dist/types/Dialog.d.ts:10:5 - (ae-forgotten-export) The symbol "show_2" needs to be exported by the entry point index.d.ts // dist/types/Notification.d.ts:8:5 - (ae-forgotten-export) The symbol "show" needs to be exported by the entry point index.d.ts // dist/types/StoryboardFunctionRegistry.d.ts:48:5 - (ae-forgotten-export) The symbol "FunctionCoverageSettings" needs to be exported by the entry point index.d.ts -// dist/types/internal/Runtime.d.ts:34:9 - (ae-forgotten-export) The symbol "AppForCheck" needs to be exported by the entry point index.d.ts +// dist/types/internal/Runtime.d.ts:35:9 - (ae-forgotten-export) The symbol "AppForCheck" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/packages/brick-container/package.json b/packages/brick-container/package.json index e131cf0fea..dfbeff7d06 100644 --- a/packages/brick-container/package.json +++ b/packages/brick-container/package.json @@ -50,7 +50,7 @@ "ws": "^8.18.0" }, "devDependencies": { - "@next-api-sdk/api-gateway-sdk": "^1.1.0", + "@next-api-sdk/api-gateway-sdk": "^1.2.2", "@next-api-sdk/micro-app-standalone-sdk": "^1.1.0", "@next-core/build-next-bricks": "^1.23.7", "@next-core/easyops-runtime": "^0.12.46", diff --git a/packages/easyops-runtime/package.json b/packages/easyops-runtime/package.json index d3bf2be7cc..520d186409 100644 --- a/packages/easyops-runtime/package.json +++ b/packages/easyops-runtime/package.json @@ -41,7 +41,7 @@ "test:ci": "cross-env NODE_ENV='test' CI=true test-next" }, "dependencies": { - "@next-api-sdk/api-gateway-sdk": "^1.2.0", + "@next-api-sdk/api-gateway-sdk": "^1.2.2", "@next-api-sdk/cmdb-sdk": "^1.1.0", "@next-api-sdk/micro-app-sdk": "^1.2.1", "@next-api-sdk/micro-app-standalone-sdk": "^1.1.0", diff --git a/packages/easyops-runtime/src/auth-v2.ts b/packages/easyops-runtime/src/auth-v2.ts index 5afc06d93c..74bd8e5cb8 100644 --- a/packages/easyops-runtime/src/auth-v2.ts +++ b/packages/easyops-runtime/src/auth-v2.ts @@ -7,7 +7,15 @@ export function authV2Factory() { const v2Kit = getV2RuntimeFromDll(); if (v2Kit) { return Object.freeze( - pick(v2Kit, ["authenticate", "getAuth", "isLoggedIn", "logout"]) + pick(v2Kit, [ + "authenticate", + "getAuth", + "isLoggedIn", + "logout", + "isBlockedPath", + "isBlockedUrl", + "isBlockedHref", + ]) ) as typeof auth; } } diff --git a/packages/easyops-runtime/src/auth.spec.ts b/packages/easyops-runtime/src/auth.spec.ts index b69f1ed4f4..357c321d2c 100644 --- a/packages/easyops-runtime/src/auth.spec.ts +++ b/packages/easyops-runtime/src/auth.spec.ts @@ -1,9 +1,26 @@ -import { authenticate, getAuth, logout, isLoggedIn } from "./auth.js"; +import { + authenticate, + getAuth, + logout, + isLoggedIn, + isBlockedPath, + isBlockedHref, + isBlockedUrl, +} from "./auth.js"; // import { resetPermissionPreChecks } from "./internal/checkPermissions.js"; // jest.mock("./internal/checkPermissions"); describe("auth", () => { + const base = document.createElement("base"); + beforeAll(() => { + base.setAttribute("href", "/next/"); + document.head.appendChild(base); + }); + afterAll(() => { + document.head.removeChild(base); + }); + it("should work", () => { expect(getAuth()).toEqual({}); expect(isLoggedIn()).toEqual(false); @@ -12,15 +29,58 @@ describe("auth", () => { username: "mock-user", userInstanceId: "abc", accessRule: "cmdb", + license: { + blackList: ["/a", "/b/:id/c"], + }, }); expect(getAuth()).toEqual({ org: 8888, username: "mock-user", userInstanceId: "abc", accessRule: "cmdb", + license: { + blackList: ["/a", "/b/:id/c"], + }, }); expect(isLoggedIn()).toEqual(true); + expect(isBlockedPath("/a")).toEqual(true); + expect(isBlockedPath("/a/123")).toEqual(true); + expect(isBlockedPath("/b")).toEqual(false); + expect(isBlockedPath("/b/123")).toEqual(false); + expect(isBlockedPath("/b/123/c")).toEqual(true); + expect(isBlockedPath("/b/123/c/d")).toEqual(true); + expect(isBlockedPath("/b/123/x")).toEqual(false); + expect(isBlockedPath("/c")).toEqual(false); + + expect(isBlockedHref("/a")).toEqual(false); + expect(isBlockedHref("/next/a")).toEqual(true); + expect(isBlockedHref("a")).toEqual(true); + expect(isBlockedHref("http://localhost/a")).toEqual(false); + expect(isBlockedHref("http://localhost/next/a")).toEqual(true); + expect(isBlockedHref("http://example.com/a")).toEqual(false); + expect(isBlockedHref("http://example.com/next/a")).toEqual(false); + + expect(isBlockedUrl("/a?q=1")).toEqual(true); + expect(isBlockedUrl("/next/a?q=1")).toEqual(false); + expect( + isBlockedUrl({ + pathname: "/a", + search: "?q=1", + }) + ).toEqual(true); + expect( + isBlockedUrl({ + pathname: "/next/a", + search: "?q=1", + }) + ).toEqual(false); + expect( + isBlockedUrl({ + search: "?q=1", + }) + ).toEqual(false); + // expect(resetPermissionPreChecks).not.toBeCalled(); logout(); expect(getAuth()).toEqual({}); diff --git a/packages/easyops-runtime/src/auth.ts b/packages/easyops-runtime/src/auth.ts index 97a423c28c..3b9a00dc54 100644 --- a/packages/easyops-runtime/src/auth.ts +++ b/packages/easyops-runtime/src/auth.ts @@ -1,4 +1,6 @@ +import { getBasePath, matchPath } from "@next-core/runtime"; import type { AuthApi_CheckLoginResponseBody } from "@next-api-sdk/api-gateway-sdk"; +import { createLocation, type LocationDescriptor } from "history"; import { resetPermissionPreChecks } from "./checkPermissions.js"; const auth: AuthInfo = {}; @@ -49,3 +51,38 @@ export function logout(): void { export function isLoggedIn(): boolean { return auth.username !== undefined; } + +/** + * 判断一个内部 URL 路径是否被屏蔽。 + */ +export function isBlockedPath(pathname: string): boolean { + return !!auth.license?.blackList?.some((path) => + matchPath(pathname, { path }) + ); +} + +/** + * 判断一个内部 URL 是否被屏蔽。 + */ +export function isBlockedUrl(url: string | LocationDescriptor): boolean { + const pathname = (typeof url === "string" ? createLocation(url) : url) + .pathname; + if (typeof pathname !== "string") { + return false; + } + return isBlockedPath(pathname); +} + +/** + * 判断一个 href 是否被屏蔽。 + */ +export function isBlockedHref(href: string): boolean { + const basePath = getBasePath(); + const url = new URL(href, `${location.origin}${basePath}`); + // 忽略外链地址 + if (url.origin !== location.origin || !url.pathname.startsWith(basePath)) { + return false; + } + // 转换为内部路径 + return isBlockedPath(url.pathname.substring(basePath.length - 1)); +} diff --git a/packages/easyops-runtime/src/menu/fetchMenuById.spec.ts b/packages/easyops-runtime/src/menu/fetchMenuById.spec.ts index 39a9daefc4..364959957e 100644 --- a/packages/easyops-runtime/src/menu/fetchMenuById.spec.ts +++ b/packages/easyops-runtime/src/menu/fetchMenuById.spec.ts @@ -9,6 +9,7 @@ import { InstalledMicroAppApi_getMenusInfo } from "@next-api-sdk/micro-app-sdk"; import { createProviderClass } from "@next-core/utils/general"; import { __test_only, createRuntime } from "@next-core/runtime"; import { YAMLException } from "js-yaml"; +import type { LocationDescriptor } from "history"; import { fetchMenuById, getMenuById } from "./fetchMenuById.js"; import type { RuntimeContext, RuntimeHelpers } from "./interfaces.js"; import * as auth from "../auth.js"; @@ -32,6 +33,14 @@ jest.mock("../auth.js", () => ({ isAdmin() { return false; }, + isBlockedUrl(url: LocationDescriptor) { + return typeof url === "string" + ? url.includes("blocked") + : url.pathname?.includes("blocked"); + }, + isBlockedHref(href: string) { + return href.includes("blocked"); + }, })); createRuntime({ @@ -91,6 +100,14 @@ const menuList = [ text: "Menu Item 6", to: '/${ APP.unknown = ["next","test"] | join : "/" }', }, + { + text: "Menu Item blocked by to", + to: "/to/blocked", + }, + { + text: "Menu Item blocked by href", + href: "/href/blocked", + }, { text: "Menu Item 7", children: [ @@ -211,7 +228,7 @@ const menuList = [ ( InstanceApi_postSearch as jest.Mock -).mockImplementation(async (objectId, data: any) => { +).mockImplementation(async (_objectId, data: any) => { return { list: menuList.filter((menu) => menu.menuId === data.query.menuId.$eq), }; diff --git a/packages/easyops-runtime/src/menu/fetchMenuById.ts b/packages/easyops-runtime/src/menu/fetchMenuById.ts index 7712650f69..d2a622d82d 100644 --- a/packages/easyops-runtime/src/menu/fetchMenuById.ts +++ b/packages/easyops-runtime/src/menu/fetchMenuById.ts @@ -11,11 +11,13 @@ import type { RuntimeMenuItemRawData, SidebarMenu, SidebarMenuItem, + SidebarMenuSimpleItem, } from "./interfaces.js"; import { computeMenuItems, computeMenuData } from "./computeMenuData.js"; import { fetchMenuTitle } from "./fetchMenuTitle.js"; import { getMenusOfStandaloneApp } from "./getMenusOfStandaloneApp.js"; import { preCheckPermissionsForAny } from "../checkPermissions.js"; +import { isBlockedHref, isBlockedUrl } from "../auth.js"; const menuPromises = new Map>(); @@ -24,30 +26,43 @@ const menuCache = new Map(); function transformMenuItems( menuItems: RuntimeMenuItemRawData[] | undefined ): SidebarMenuItem[] | undefined { - return menuItems?.filter(checkIfOfComputed).map((item) => { - const children = transformMenuItems(item.children); - const transformedMenuItem: SidebarMenuItem = - item.type === "group" - ? { - type: "group", - title: item.text, - childLayout: item.childLayout, - items: children, - groupId: item.groupId, - groupFrom: item.groupFrom, - } - : children?.length + return menuItems + ?.filter(checkIfOfComputed) + .map((item) => { + const children = transformMenuItems(item.children); + const transformedMenuItem: SidebarMenuItem | null = + item.type === "group" ? { - type: "subMenu", - childLayout: item.childLayout, + type: "group", title: item.text, - icon: item.icon, + childLayout: item.childLayout, items: children, - defaultExpanded: item.defaultExpanded, + groupId: item.groupId, + groupFrom: item.groupFrom, } - : (omit(item, ["type", "items", "children"]) as SidebarMenuItem); - return transformedMenuItem; - }); + : children?.length + ? { + type: "subMenu", + childLayout: item.childLayout, + title: item.text, + icon: item.icon, + items: children, + defaultExpanded: item.defaultExpanded, + } + : isMenuItemBlocked(item as SidebarMenuSimpleItem) + ? null + : (omit(item, ["type", "items", "children"]) as SidebarMenuItem); + return transformedMenuItem; + }) + .filter(Boolean) as SidebarMenuItem[]; +} + +function isMenuItemBlocked(item: SidebarMenuSimpleItem) { + return item.href + ? isBlockedHref(item.href) + : item.to + ? isBlockedUrl(item.to) + : false; } export function getMenuById(menuId: string) { diff --git a/packages/easyops-runtime/src/menu/interfaces.ts b/packages/easyops-runtime/src/menu/interfaces.ts index 622f70ec52..b5b242dedd 100644 --- a/packages/easyops-runtime/src/menu/interfaces.ts +++ b/packages/easyops-runtime/src/menu/interfaces.ts @@ -4,6 +4,7 @@ import type { __secret_internals, MatchOptions, } from "@next-core/runtime"; +import type { LocationDescriptor } from "history"; import { symbolAppId, symbolMenuI18nNamespace, @@ -61,8 +62,7 @@ export interface SidebarMenuSimpleItem { text: string; /** 菜单项对应的系统内地址。 */ - // to?: LocationDescriptor; - to?: unknown; + to?: LocationDescriptor; /** 菜单项对应的外部链接地址。 */ href?: string; diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 7f48497d2c..f7fdabbb46 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -62,7 +62,7 @@ }, "devDependencies": { "@microsoft/api-extractor": "^7.47.9", - "@next-api-sdk/api-gateway-sdk": "^1.1.0", + "@next-api-sdk/api-gateway-sdk": "^1.2.2", "@next-api-sdk/micro-app-sdk": "^1.2.1", "@next-core/build-next-libs": "^1.0.21", "@next-core/test-next": "^1.1.7" diff --git a/packages/runtime/src/internal/ErrorNode.spec.ts b/packages/runtime/src/internal/ErrorNode.spec.ts index 6228848b6b..9fdb3959e2 100644 --- a/packages/runtime/src/internal/ErrorNode.spec.ts +++ b/packages/runtime/src/internal/ErrorNode.spec.ts @@ -1,7 +1,7 @@ import { jest, describe, test, expect } from "@jest/globals"; import { BrickLoadError, loadBricksImperatively } from "@next-core/loader"; import { initializeI18n } from "@next-core/i18n"; -import { ErrorNode, PageNotFoundError } from "./ErrorNode.js"; +import { ErrorNode, PageError } from "./ErrorNode.js"; import { RenderTag } from "./enums.js"; import type { RenderReturnNode } from "./interfaces.js"; import { HttpResponseError } from "@next-core/http"; @@ -262,7 +262,7 @@ describe("ErrorNode", () => { test("page not found", async () => { expect( await ErrorNode( - new PageNotFoundError("page not found"), + new PageError("page not found"), { tag: RenderTag.ROOT, } as RenderReturnNode, @@ -297,7 +297,7 @@ describe("ErrorNode", () => { test("app not found", async () => { expect( await ErrorNode( - new PageNotFoundError("app not found"), + new PageError("app not found"), { tag: RenderTag.ROOT, } as RenderReturnNode, @@ -336,7 +336,7 @@ describe("ErrorNode", () => { expect( await ErrorNode( - new PageNotFoundError("app not found"), + new PageError("app not found"), { tag: RenderTag.ROOT, } as RenderReturnNode, diff --git a/packages/runtime/src/internal/ErrorNode.ts b/packages/runtime/src/internal/ErrorNode.ts index e6c0b9a189..957a60b828 100644 --- a/packages/runtime/src/internal/ErrorNode.ts +++ b/packages/runtime/src/internal/ErrorNode.ts @@ -24,12 +24,12 @@ interface ErrorMessageConfig { type LinkType = "home" | "previous" | "reload"; -export class PageNotFoundError extends Error { - constructor(message: "page not found" | "app not found") { +export class PageError extends Error { + constructor(message: "page blocked" | "page not found" | "app not found") { // Pass remaining arguments (including vendor specific ones) to parent constructor super(message); - this.name = "PageNotFoundError"; + this.name = "PageError"; // Maintains proper stack trace for where our error was thrown (only available on V8) // istanbul ignore else @@ -182,18 +182,24 @@ function getLinkNode( } function getRefinedErrorConf(error: unknown): ErrorMessageConfig { - if (error instanceof PageNotFoundError) { - return error.message === "app not found" + if (error instanceof PageError) { + return error.message === "page blocked" ? { showLink: "home", - title: i18n.t(`${NS}:${K.APP_NOT_FOUND}`), + title: i18n.t(`${NS}:${K.LICENSE_BLOCKED}`), variant: "no-permission", } - : { - showLink: "home", - variant: "not-found", - title: i18n.t(`${NS}:${K.PAGE_NOT_FOUND}`), - }; + : error.message === "app not found" + ? { + showLink: "home", + title: i18n.t(`${NS}:${K.APP_NOT_FOUND}`), + variant: "no-permission", + } + : { + showLink: "home", + variant: "not-found", + title: i18n.t(`${NS}:${K.PAGE_NOT_FOUND}`), + }; } if ( diff --git a/packages/runtime/src/internal/Router.ts b/packages/runtime/src/internal/Router.ts index f67a0c23e0..5cba5b8459 100644 --- a/packages/runtime/src/internal/Router.ts +++ b/packages/runtime/src/internal/Router.ts @@ -55,7 +55,7 @@ import { setUIVersion } from "../setUIVersion.js"; import { setAppVariable } from "../setAppVariable.js"; import { setWatermark } from "../setWatermark.js"; import { clearMatchedRoutes } from "./routeMatchedMap.js"; -import { ErrorNode, PageNotFoundError } from "./ErrorNode.js"; +import { ErrorNode, PageError } from "./ErrorNode.js"; import { resetReloadForError, shouldReloadForError, @@ -277,6 +277,7 @@ export class Router { async #render(location: NextLocation, isBootstrap: boolean): Promise { const renderId = (this.#renderId = uniqueId("render-id-")); + const blocked = hooks?.auth?.isBlockedPath?.(location.pathname); resetAllComputedMarks(); clearResolveCache(); @@ -288,7 +289,9 @@ export class Router { // const renderStartTime = performance.now(); const finishPageView = hooks?.pageView?.create(); - const storyboard = matchStoryboard(this.#storyboards, location.pathname); + const storyboard = blocked + ? undefined + : matchStoryboard(this.#storyboards, location.pathname); const previousApp = this.#runtimeContext?.app; const currentAppId = storyboard?.app?.id; @@ -576,7 +579,13 @@ export class Router { applyMode(); const node = await ErrorNode( - new PageNotFoundError(currentApp ? "page not found" : "app not found"), + new PageError( + blocked + ? "page blocked" + : currentApp + ? "page not found" + : "app not found" + ), renderRoot, true ); @@ -586,7 +595,7 @@ export class Router { // Scroll to top after each rendering. window.scrollTo(0, 0); - finishPageView?.({ status: "not-found" }); + finishPageView?.({ status: blocked ? "blocked" : "not-found" }); devtoolsHookEmit("rendered"); } } diff --git a/packages/runtime/src/internal/Runtime.spec.ts b/packages/runtime/src/internal/Runtime.spec.ts index 322ef917ea..2d6663b421 100644 --- a/packages/runtime/src/internal/Runtime.spec.ts +++ b/packages/runtime/src/internal/Runtime.spec.ts @@ -1688,6 +1688,70 @@ describe("Runtime", () => { expect(finishPageView).toHaveBeenNthCalledWith(2, { status: "not-found" }); }); + test("page blocked", async () => { + window.NO_AUTH_GUARD = false; + const finishPageView = jest.fn(); + createRuntime({ + hooks: { + auth: { + isLoggedIn() { + return true; + }, + getAuth() { + return {}; + }, + isBlockedPath() { + return true; + }, + }, + pageView: { + create: jest.fn(() => finishPageView), + }, + }, + }).initialize({ + storyboards: [ + { + app: { + id: "blocked-app", + homepage: "/blocked-app", + name: "Blocked APP", + }, + routes: [ + { + path: "${APP.homepage}/blocked", + bricks: [{ brick: "div" }], + }, + ], + }, + ], + brickPackages: [], + }); + getHistory().push("/blocked-app/blocked"); + await getRuntime().bootstrap(); + expect(document.body.children).toMatchInlineSnapshot(` + HTMLCollection [ +
+ + + Go back to home page + + +
, +
, + ] + `); + expect(finishPageView).toBeCalledTimes(1); + expect(finishPageView).toBeCalledWith({ + status: "blocked", + }); + }); + test("failed to bootstrap", async () => { consoleError.mockReturnValueOnce(); const finishPageView = jest.fn(); diff --git a/packages/runtime/src/internal/Runtime.ts b/packages/runtime/src/internal/Runtime.ts index 06ccf1b892..598aa7549a 100644 --- a/packages/runtime/src/internal/Runtime.ts +++ b/packages/runtime/src/internal/Runtime.ts @@ -45,7 +45,7 @@ export interface ImagesFactory { } export interface PageViewInfo { - status: "ok" | "failed" | "redirected" | "not-found"; + status: "ok" | "failed" | "redirected" | "not-found" | "blocked"; path?: string; pageTitle?: string; } @@ -56,6 +56,7 @@ export interface RuntimeHooks { isLoggedIn(): boolean; authenticate?(...args: unknown[]): unknown; logout?(...args: unknown[]): unknown; + isBlockedPath?(pathname: string): boolean; }; fulfilStoryboard?: (storyboard: RuntimeStoryboard) => Promise; validatePermissions?: typeof PermissionApi_validatePermissions; diff --git a/packages/runtime/src/internal/i18n.ts b/packages/runtime/src/internal/i18n.ts index d11497643b..60d14a13e9 100644 --- a/packages/runtime/src/internal/i18n.ts +++ b/packages/runtime/src/internal/i18n.ts @@ -4,6 +4,7 @@ export enum K { LOGIN_TIMEOUT_MESSAGE = "LOGIN_TIMEOUT_MESSAGE", NETWORK_ERROR = "NETWORK_ERROR", LICENSE_EXPIRED = "LICENSE_EXPIRED", + LICENSE_BLOCKED = "LICENSE_BLOCKED", NO_PERMISSION = "NO_PERMISSION", PAGE_NOT_FOUND = "PAGE_NOT_FOUND", APP_NOT_FOUND = "APP_NOT_FOUND", @@ -21,6 +22,8 @@ const en: Locale = { [K.NETWORK_ERROR]: "Network error, please check your network.", [K.LICENSE_EXPIRED]: "The license authorization has expired, please contact the platform administrator", + [K.LICENSE_BLOCKED]: + "The page is not authorized, please contact the platform administrator", [K.NO_PERMISSION]: "Unauthorized access, unable to retrieve the required resources for this page", [K.PAGE_NOT_FOUND]: "Page not found, please check the URL", @@ -38,6 +41,7 @@ const zh: Locale = { [K.LOGIN_TIMEOUT_MESSAGE]: "您还未登录或登录信息已过期,现在重新登录?", [K.NETWORK_ERROR]: "网络错误,请检查您的网络连接。", [K.LICENSE_EXPIRED]: "License 授权失效,请联系平台管理员", + [K.LICENSE_BLOCKED]: "该页面未授权,请联系平台管理员", [K.NO_PERMISSION]: "没有权限,无法获取页面所需要的资源", [K.PAGE_NOT_FOUND]: "请求的页面未找到,请确认 URL 是否正确", [K.APP_NOT_FOUND]: "请求的微应用无法找到, 可能是 URL 错误或者无权限访问", diff --git a/yarn.lock b/yarn.lock index e29ff4e3e5..6871e4d5ea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1968,12 +1968,12 @@ resolved "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz#f29a55df17cb6e87cfbabce33ff6a14a9f85076d" integrity sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA== -"@next-api-sdk/api-gateway-sdk@^1.1.0", "@next-api-sdk/api-gateway-sdk@^1.2.0": - version "1.2.0" - resolved "https://registry.npmjs.org/@next-api-sdk/api-gateway-sdk/-/api-gateway-sdk-1.2.0.tgz#68a49bf50f76c626234ce53cb3606f7dbeb2ca97" - integrity sha512-HG6wSG2hoH+ZXEH/AUIsbhUwtzXQgWKU7usrFVVQsGmqIQscjRYMSlCqEAJixP1IG9vQ0D+kkkaeAoSnhX3nEg== +"@next-api-sdk/api-gateway-sdk@^1.2.2": + version "1.2.2" + resolved "https://registry.npmjs.org/@next-api-sdk/api-gateway-sdk/-/api-gateway-sdk-1.2.2.tgz#867b2b93573379fcd8f2507876bc0ce83bf19858" + integrity sha512-q4XFL3xOAcG+qboXWKRfENiiN72dVIs0w9JBurVj5NwbgSsF3L4L1T+v1MJlBIp7hhEzWa60SwvUh0IiRneNqA== dependencies: - "@next-core/http" "^1.0.0" + "@next-core/http" "^1.2.6" "@next-api-sdk/cmdb-sdk@^1.1.0": version "1.1.0"