From f1b8f0c087187d511bce0d217ce72901e3c6a6a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=90=9A=E8=87=B4=E8=BF=9C?= Date: Thu, 15 Apr 2021 17:29:00 +0800 Subject: [PATCH] feat: added types for Plugins (#1736) --- ...create-edit-delete-plugin-template.spec.js | 6 +- ...route-with-limit-count-plugin-form.spec.js | 2 + web/src/components/Plugin/PluginPage.tsx | 33 ++-- web/src/components/Plugin/data.tsx | 164 +++++++++++++++++- web/src/components/Plugin/locales/en-US.ts | 8 + web/src/components/Plugin/locales/zh-CN.ts | 8 + web/src/components/Plugin/service.ts | 16 +- web/src/components/Plugin/typing.d.ts | 3 +- web/src/pages/Plugin/locales/en-US.ts | 2 +- web/src/pages/Plugin/locales/zh-CN.ts | 2 +- 10 files changed, 222 insertions(+), 22 deletions(-) diff --git a/web/cypress/integration/pluginTemplate/create-edit-delete-plugin-template.spec.js b/web/cypress/integration/pluginTemplate/create-edit-delete-plugin-template.spec.js index ea0a4dde48..cd3a2a4857 100644 --- a/web/cypress/integration/pluginTemplate/create-edit-delete-plugin-template.spec.js +++ b/web/cypress/integration/pluginTemplate/create-edit-delete-plugin-template.spec.js @@ -40,8 +40,10 @@ context('Create Configure and Delete PluginTemplate', () => { // should not see proxy-rewrite plugin in the step2 cy.contains('proxy-rewrite').should('not.exist'); - cy.contains('Enable').click({ - force: true + cy.contains(this.domSelector.pluginCard, 'basic-auth').within(() => { + cy.contains('Enable').click({ + force: true, + }); }); cy.focused(this.domSelector.drawer).should('exist'); diff --git a/web/cypress/integration/route/create-route-with-limit-count-plugin-form.spec.js b/web/cypress/integration/route/create-route-with-limit-count-plugin-form.spec.js index 7992f2c085..f9db28bb56 100644 --- a/web/cypress/integration/route/create-route-with-limit-count-plugin-form.spec.js +++ b/web/cypress/integration/route/create-route-with-limit-count-plugin-form.spec.js @@ -51,6 +51,8 @@ context('Create and delete route with limit-count form', () => { cy.contains('Next').click(); cy.get(this.domSelector.nodes_0_host).type('127.0.0.1'); + cy.get(this.domSelector.nodes_0_port).clear().type(this.data.port); + cy.get(this.domSelector.nodes_0_weight).clear().type(this.data.weight); cy.contains('Next').click(); // config limit-count form with local policy diff --git a/web/src/components/Plugin/PluginPage.tsx b/web/src/components/Plugin/PluginPage.tsx index fa30a739e8..61e9bee6d0 100644 --- a/web/src/components/Plugin/PluginPage.tsx +++ b/web/src/components/Plugin/PluginPage.tsx @@ -67,7 +67,6 @@ const PluginPage: React.FC = ({ const [typeList, setTypeList] = useState([]); const [plugins, setPlugins] = useState({}); - const firstUpperCase = ([first, ...rest]: string) => first.toUpperCase() + rest.join(''); useEffect(() => { setPlugins(initialData); fetchList().then((data) => { @@ -80,11 +79,11 @@ const PluginPage: React.FC = ({ setPluginList(filteredData); const categoryList: string[] = []; data.forEach((item) => { - if (!categoryList.includes(firstUpperCase(item.type))) { - categoryList.push(firstUpperCase(item.type)); + if (!categoryList.includes(item.type)) { + categoryList.push(item.type); } }); - setTypeList(categoryList.sort()); + setTypeList(categoryList); }); fetchPluginTemplateList().then((data) => { setPluginTemplateList(data); @@ -96,20 +95,24 @@ const PluginPage: React.FC = ({ <> {typeList.map((typeItem) => { return ( - + ); })} @@ -166,13 +169,13 @@ const PluginPage: React.FC = ({ {typeList.map((typeItem) => { return ( {orderBy( - pluginList.filter((item) => item.type === typeItem.toLowerCase()), + pluginList.filter((item) => item.type === typeItem.toLowerCase() && !item.hidden), 'name', 'asc', ).map((item) => ( diff --git a/web/src/components/Plugin/data.tsx b/web/src/components/Plugin/data.tsx index dc6db0ce65..df119c1f24 100644 --- a/web/src/components/Plugin/data.tsx +++ b/web/src/components/Plugin/data.tsx @@ -30,5 +30,167 @@ export const PLUGIN_ICON_LIST: Record = { // This list is used to filter out plugins that cannot be displayed in the plugins list. export const PLUGIN_FILTER_LIST: Record = { redirect: { list: ['route'] }, // Filter out the redirect plugin on the route page. - 'proxy-rewrite': { list: ['route']}, + 'proxy-rewrite': { list: ['route'] }, }; + +export enum PluginType { + authentication = "authentication", + security = "security", + traffic = "traffic", + serverless = "serverless", + observability = "observability", + logging = "logging", + other = "other" +} + +/** + * Plugin List that contains type field +*/ +export const PLUGIN_LIST = { + "hmac-auth": { + type: PluginType.authentication + }, + "serverless-post-function": { + type: PluginType.serverless + }, + "mqtt-proxy": { + type: PluginType.other, + hidden: true + }, + "response-rewrite": { + type: PluginType.other + }, + "basic-auth": { + type: PluginType.authentication + }, + "error-log-logger": { + type: PluginType.logging + }, + "fault-injection": { + type: PluginType.security + }, + "limit-count": { + type: PluginType.traffic + }, + "prometheus": { + type: PluginType.observability + }, + "proxy-rewrite": { + type: PluginType.other + }, + "syslog": { + type: PluginType.logging + }, + "traffic-split": { + type: PluginType.traffic + }, + "jwt-auth": { + type: PluginType.authentication + }, + "kafka-logger": { + type: PluginType.logging + }, + "limit-conn": { + type: PluginType.traffic + }, + "udp-logger": { + type: PluginType.logging + }, + "zipkin": { + type: PluginType.observability + }, + "echo": { + type: PluginType.other, + hidden: true + }, + "log-rotate": { + type: PluginType.logging, + hidden: true + }, + "serverless-pre-function": { + type: PluginType.serverless + }, + "dubbo-proxy": { + type: PluginType.other, + hidden: true + }, + "node-status": { + type: PluginType.other, + hidden: true + }, + "referer-restriction": { + type: PluginType.security + }, + "api-breaker": { + type: PluginType.security, + }, + "consumer-restriction": { + type: PluginType.security + }, + "cors": { + type: PluginType.security + }, + "limit-req": { + type: PluginType.traffic + }, + "proxy-mirror": { + type: PluginType.other + }, + "request-validation": { + type: PluginType.security + }, + "example-plugin": { + type: PluginType.other, + hidden: true + }, + "ip-restriction": { + type: PluginType.security + }, + "key-auth": { + type: PluginType.authentication + }, + "proxy-cache": { + type: PluginType.other + }, + "redirect": { + type: PluginType.other, + hidden: true + }, + "request-id": { + type: PluginType.observability + }, + "skywalking": { + type: PluginType.observability + }, + "batch-requests": { + type: PluginType.other + }, + "http-logger": { + type: PluginType.logging + }, + "openid-connect": { + type: PluginType.authentication + }, + "sls-logger": { + type: PluginType.logging + }, + "tcp-logger": { + type: PluginType.logging + }, + "uri-blocker": { + type: PluginType.security + }, + "wolf-rbac": { + type: PluginType.other + }, + "authz-keycloak": { + type: PluginType.authentication + }, + "grpc-transcode": { + type: PluginType.other + }, + "server-info": { + type: PluginType.other, + hidden: true + } +} diff --git a/web/src/components/Plugin/locales/en-US.ts b/web/src/components/Plugin/locales/en-US.ts index 10363bd85d..26fa357e80 100644 --- a/web/src/components/Plugin/locales/en-US.ts +++ b/web/src/components/Plugin/locales/en-US.ts @@ -21,6 +21,14 @@ export default { 'component.step.select.pluginTemplate.select.option': 'Custom', 'component.plugin.pluginTemplate.tip1': '1. When a route already have plugins field configured, the plugins in the plugin template will be merged into it.', 'component.plugin.pluginTemplate.tip2': '2. The same plugin in the plugin template will override one in the plugins', + 'component.plugin.authentication': 'Authentication', + 'component.plugin.security': 'Security', + 'component.plugin.traffic': 'Traffic Control', + 'component.plugin.serverless': 'Serverless', + 'component.plugin.observability': 'Tracing & Metrics & Logging', + 'component.plugin.logging': 'Logging', + 'component.plugin.other': 'Other', + // cors 'component.pluginForm.cors.allow_origins.tooltip': 'Which Origins is allowed to enable CORS, format as:scheme://host:port, for example: https://somehost.com:8081. Multiple origin use , to split. When allow_credential is false, you can use * to indicate allow any origin. you also can allow all any origins forcefully using ** even already enable allow_credential, but it will bring some security risks.', 'component.pluginForm.cors.allow_origins.extra': 'For example: https://somehost.com:8081', diff --git a/web/src/components/Plugin/locales/zh-CN.ts b/web/src/components/Plugin/locales/zh-CN.ts index 6d25eb4ea8..b88f6e80d1 100644 --- a/web/src/components/Plugin/locales/zh-CN.ts +++ b/web/src/components/Plugin/locales/zh-CN.ts @@ -21,6 +21,14 @@ export default { 'component.step.select.pluginTemplate.select.option': '手动配置', 'component.plugin.pluginTemplate.tip1': '1. 若路由已配置插件,则插件模板数据将与已配置的插件数据合并。', 'component.plugin.pluginTemplate.tip2': '2. 插件模板相同的插件会覆盖掉原有的插件。', + 'component.plugin.authentication': '身份验证', + 'component.plugin.security': '安全防护', + 'component.plugin.traffic': '流量控制', + 'component.plugin.serverless': '无服务器架构', + 'component.plugin.observability': '可观测性', + 'component.plugin.logging': '日志记录', + 'component.plugin.other': '其它', + // cors 'component.pluginForm.cors.allow_origins.tooltip': '允许跨域访问的 Origin,格式如:scheme://host:port,比如: https://somehost.com:8081 。多个值使用 , 分割,allow_credential 为 false 时可以使用 * 来表示所有 Origin 均允许通过。你也可以在启用了 allow_credential 后使用 ** 强制允许所有 Origin 都通过,但请注意这样存在安全隐患。', 'component.pluginForm.cors.allow_origins.extra': '例如: https://somehost.com:8081', diff --git a/web/src/components/Plugin/service.ts b/web/src/components/Plugin/service.ts index 5a1b42724e..89c7fee953 100644 --- a/web/src/components/Plugin/service.ts +++ b/web/src/components/Plugin/service.ts @@ -17,9 +17,23 @@ import { omit } from 'lodash'; import { request } from 'umi'; +import { PLUGIN_LIST, PluginType } from './data'; + export const fetchList = () => { return request>('/plugins?all=true').then((data) => { - return data.data; + const typedData = data.data.map(item => ({ + ...item, + type: PLUGIN_LIST[item.name]?.type || "other", + hidden: PLUGIN_LIST[item.name]?.hidden || false + })); + + let finalList: PluginComponent.Meta[] = [] + + Object.values(PluginType).forEach(type => { + finalList = finalList.concat(typedData.filter(item => item.type === type)) + }) + + return finalList }); }; diff --git a/web/src/components/Plugin/typing.d.ts b/web/src/components/Plugin/typing.d.ts index c92b882f56..0fe2052cfb 100644 --- a/web/src/components/Plugin/typing.d.ts +++ b/web/src/components/Plugin/typing.d.ts @@ -26,9 +26,10 @@ declare namespace PluginComponent { type: string; version: number; consumer_schema?: Record; + hidden?: boolean; }; type ReferPage = '' | 'route' | 'consumer' | 'service' | 'plugin'; - type CodeMirrorMode = 'JSON' | 'YAML'| 'Form'; + type CodeMirrorMode = 'JSON' | 'YAML' | 'Form'; } diff --git a/web/src/pages/Plugin/locales/en-US.ts b/web/src/pages/Plugin/locales/en-US.ts index 72ad832316..16e45f824a 100644 --- a/web/src/pages/Plugin/locales/en-US.ts +++ b/web/src/pages/Plugin/locales/en-US.ts @@ -18,5 +18,5 @@ export default { 'page.plugin.drawer.popconfirm.title.delete': 'Are you sure to delete this item?', 'page.plugin.list': 'Plugin List', 'page.plugin.list.enabled': 'List of enabled plugins', - 'page.plugin.market.config': 'Configure Plugin', + 'page.plugin.market.config': 'Global Plugin List', }; diff --git a/web/src/pages/Plugin/locales/zh-CN.ts b/web/src/pages/Plugin/locales/zh-CN.ts index 2ceb8546f2..991532332d 100644 --- a/web/src/pages/Plugin/locales/zh-CN.ts +++ b/web/src/pages/Plugin/locales/zh-CN.ts @@ -18,5 +18,5 @@ export default { 'page.plugin.drawer.popconfirm.title.delete': '确定删除该插件吗?', 'page.plugin.list': '插件列表', 'page.plugin.list.enabled': '已启用插件的列表', - 'page.plugin.market.config': '配置列表', + 'page.plugin.market.config': '全局插件列表', };