├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ ├── docs_issue.yml │ ├── feature_request.yml │ └── request_help.yml └── workflows │ └── release.yaml ├── .gitignore ├── .gitlab-ci.yml ├── .golangci.yml ├── .goreleaser.yaml ├── README.md ├── app ├── .gitignore ├── apserver │ ├── .gitignore │ ├── apserver.go │ ├── driver.go │ ├── embed_plugin.go │ ├── log.go │ ├── main.go │ ├── services.go │ └── version │ │ ├── dashboard.go │ │ └── version.go └── dynamic-module │ ├── .gitignore │ ├── file-access-log │ ├── README.md │ ├── plugin.yml │ └── 文件日志.png │ ├── http-access-log │ ├── HTTP日志.png │ ├── README.md │ └── plugin.yml │ ├── influxdb │ ├── InfluxDB配置.png │ ├── README.md │ └── plugin.yml │ ├── kafka-access-log │ ├── Kafka日志.png │ ├── README.md │ └── plugin.yml │ ├── nsqd-access-log │ ├── NSQ日志.png │ ├── README.md │ └── plugin.yml │ ├── package.sh │ ├── redis │ ├── README.md │ ├── Redis配置.png │ └── plugin.yml │ └── syslog-access-log │ ├── README.md │ ├── SYSLOG日志.png │ └── plugin.yml ├── cache ├── common-cache-mock │ └── common-cache_mock.go ├── common.go ├── init.go ├── lock.go ├── locker.go └── redis_cache.go ├── client ├── v1 │ ├── cert_api.go │ ├── client.go │ ├── client_test.go │ ├── extender_api.go │ ├── http_request.go │ ├── initialize │ │ └── plugin │ │ │ ├── apinto_plugin.yml │ │ │ ├── black_extended.go │ │ │ ├── black_extended.yml │ │ │ └── global.go │ ├── model.go │ ├── plugin_api.go │ ├── profession.go │ ├── proxy.go │ ├── service.go │ ├── strategy.go │ └── variable_api.go └── v2 │ ├── app.go │ ├── client.go │ ├── client_test.go │ ├── cluster.go │ ├── manager.go │ ├── status.go │ └── worker.go ├── common ├── aes.go ├── base64.go ├── cert.go ├── compress.go ├── const.go ├── diff.go ├── email.go ├── email_test.go ├── error.go ├── float64.go ├── gzip-static │ ├── gzip.go │ ├── gzip_test.go │ ├── handler.go │ └── options.go ├── http.go ├── interface_to_all.go ├── json.go ├── jwt.go ├── map.go ├── md5.go ├── panic.go ├── path.go ├── pool.go ├── rand.go ├── regexp.go ├── restful │ ├── builder.go │ ├── data.go │ ├── path.go │ ├── path_test.go │ ├── request-call.go │ ├── request-oneway.go │ ├── request-rpc.go │ ├── request-simple.go │ ├── request.go │ ├── restful.go │ └── restful_test.go ├── schema │ ├── README.md │ ├── schema.go │ └── schema_test.go ├── slice.go ├── slice_to_all.go ├── slices.go ├── time.go ├── webhook.go ├── webhook_test.go └── yml.go ├── config ├── config.go ├── dir.go ├── redis.go ├── store-mysql.go └── store.go ├── controller ├── .gitignore ├── audit.go ├── filters.go ├── gin_context.go ├── result.go └── users │ └── user.go ├── driver └── driver_manager.go ├── enum ├── api_manager.go ├── change_opt_type.go ├── cluster_config.go ├── cluster_node_status.go ├── cluster_plugin.go ├── cluster_status.go ├── common.go ├── keyword.go ├── online_status_type.go ├── publish_opt.go ├── publish_type.go └── variable_usage_status_type.go ├── filter └── filter.go ├── frontend ├── .eslintrc.js ├── .gitignore ├── .npmrc ├── .prettierrc.json ├── .yarnrc ├── README.md ├── angular.json ├── frontend.go ├── jest.config.ts ├── package.json ├── projects │ ├── core │ │ └── src │ │ │ ├── app │ │ │ ├── app-routing.module.ts │ │ │ ├── app.component.ts │ │ │ ├── app.module.ts │ │ │ ├── component │ │ │ │ ├── api-method-tag │ │ │ │ │ └── api-method-tag.component.ts │ │ │ │ ├── card-list │ │ │ │ │ └── card-list.component.ts │ │ │ │ ├── component.module.ts │ │ │ │ ├── copy-addr-list │ │ │ │ │ └── copy-addr-list.component.ts │ │ │ │ ├── dynamic-component │ │ │ │ │ ├── dynamic-component.component.html │ │ │ │ │ └── dynamic-component.component.ts │ │ │ │ ├── editable-env-table │ │ │ │ │ ├── editable-env-table.component.html │ │ │ │ │ ├── editable-env-table.component.ts │ │ │ │ │ └── editable-env-table.service.ts │ │ │ │ ├── eo-ng-search-input-group │ │ │ │ │ └── eo-ng-search-input-group.component.ts │ │ │ │ ├── formily2-react │ │ │ │ │ ├── CustomReactComponentWrapper.tsx │ │ │ │ │ ├── IntelligentPluginEditComponent.tsx │ │ │ │ │ ├── component │ │ │ │ │ │ ├── array-item-blank │ │ │ │ │ │ │ ├── ArrayItemBlankComponent.tsx │ │ │ │ │ │ │ ├── ArrayItemBlankWrapperComponent.tsx │ │ │ │ │ │ │ └── test-blank.json │ │ │ │ │ │ ├── codebox │ │ │ │ │ │ │ ├── CustomCodeboxComponent.tsx │ │ │ │ │ │ │ └── CustomCodeboxComponentWrapper.tsx │ │ │ │ │ │ ├── dialog │ │ │ │ │ │ │ ├── CustomDialogComponent.tsx │ │ │ │ │ │ │ └── CustomDialogComponentWrapper.tsx │ │ │ │ │ │ ├── editable-env-table │ │ │ │ │ │ │ ├── CustomEnvVariableComponent.tsx │ │ │ │ │ │ │ ├── CustomEnvVariableComponentWrapper.tsx │ │ │ │ │ │ │ └── CustomEnvVariableTableComponent.tsx │ │ │ │ │ │ └── simple-map │ │ │ │ │ │ │ ├── SimpleMapComponent.tsx │ │ │ │ │ │ │ └── SimpleMapComponentWrapper.tsx │ │ │ │ │ └── formily2-react.component.ts │ │ │ │ ├── iframe │ │ │ │ │ ├── iframe.component.html │ │ │ │ │ └── iframe.component.ts │ │ │ │ ├── intelligent-plugin │ │ │ │ │ ├── create │ │ │ │ │ │ ├── create.component.html │ │ │ │ │ │ └── create.component.ts │ │ │ │ │ ├── intelligent-plugin.service.ts │ │ │ │ │ ├── layout │ │ │ │ │ │ ├── layout.component.html │ │ │ │ │ │ └── layout.component.ts │ │ │ │ │ ├── list │ │ │ │ │ │ ├── list.component.html │ │ │ │ │ │ └── list.component.ts │ │ │ │ │ ├── publish │ │ │ │ │ │ ├── publish.component.html │ │ │ │ │ │ └── publish.component.ts │ │ │ │ │ └── types │ │ │ │ │ │ ├── conf.ts │ │ │ │ │ │ └── types.ts │ │ │ │ ├── reset-psw │ │ │ │ │ ├── reset-psw.component.html │ │ │ │ │ └── reset-psw.component.ts │ │ │ │ ├── table-status-td │ │ │ │ │ └── table-status-td.component.ts │ │ │ │ ├── user-avatar │ │ │ │ │ ├── user-avatar.component.html │ │ │ │ │ ├── user-avatar.component.scss │ │ │ │ │ └── user-avatar.component.ts │ │ │ │ └── user-profile │ │ │ │ │ ├── user-profile.component.html │ │ │ │ │ └── user-profile.component.ts │ │ │ ├── constant │ │ │ │ ├── app.config.ts │ │ │ │ ├── conf.ts │ │ │ │ ├── eo-ng-validator.ts │ │ │ │ ├── form.ts │ │ │ │ ├── spec-test.ts │ │ │ │ └── type.ts │ │ │ ├── custom-preloading-strategy.ts │ │ │ ├── directive │ │ │ │ ├── auto-focus.directive.ts │ │ │ │ ├── directive.module.ts │ │ │ │ ├── eo-ng-scroll-dom.directive.ts │ │ │ │ ├── row-expand-button.directive.ts │ │ │ │ ├── tree-drag.directive.ts │ │ │ │ └── user-access.directive.ts │ │ │ ├── layout │ │ │ │ ├── api │ │ │ │ │ ├── api-list │ │ │ │ │ │ ├── api-list.component.ts │ │ │ │ │ │ ├── create │ │ │ │ │ │ │ ├── http-create │ │ │ │ │ │ │ │ ├── http-create.component.spec.ts │ │ │ │ │ │ │ │ └── http-create.component.ts │ │ │ │ │ │ │ └── websocket-create │ │ │ │ │ │ │ │ ├── websocket-create.component.html │ │ │ │ │ │ │ │ ├── websocket-create.component.spec.ts │ │ │ │ │ │ │ │ └── websocket-create.component.ts │ │ │ │ │ │ ├── group │ │ │ │ │ │ │ ├── edit-group │ │ │ │ │ │ │ │ ├── edit-group.component.spec.ts │ │ │ │ │ │ │ │ └── edit-group.component.ts │ │ │ │ │ │ │ ├── group.component.html │ │ │ │ │ │ │ ├── group.component.spec.ts │ │ │ │ │ │ │ └── group.component.ts │ │ │ │ │ │ ├── import │ │ │ │ │ │ │ ├── import.component.html │ │ │ │ │ │ │ ├── import.component.spec.ts │ │ │ │ │ │ │ └── import.component.ts │ │ │ │ │ │ ├── list │ │ │ │ │ │ │ ├── list.component.html │ │ │ │ │ │ │ ├── list.component.spec.ts │ │ │ │ │ │ │ └── list.component.ts │ │ │ │ │ │ ├── match │ │ │ │ │ │ │ ├── form │ │ │ │ │ │ │ │ ├── form.component.html │ │ │ │ │ │ │ │ ├── form.component.spec.ts │ │ │ │ │ │ │ │ └── form.component.ts │ │ │ │ │ │ │ └── table │ │ │ │ │ │ │ │ ├── table.component.html │ │ │ │ │ │ │ │ ├── table.component.spec.ts │ │ │ │ │ │ │ │ └── table.component.ts │ │ │ │ │ │ ├── message │ │ │ │ │ │ │ ├── http-message │ │ │ │ │ │ │ │ └── http-message.component.ts │ │ │ │ │ │ │ ├── message.component.spec.ts │ │ │ │ │ │ │ ├── message.component.ts │ │ │ │ │ │ │ └── websocket-message │ │ │ │ │ │ │ │ └── websocket-message.component.ts │ │ │ │ │ │ ├── proxy │ │ │ │ │ │ │ ├── proxy.component.html │ │ │ │ │ │ │ ├── proxy.component.spec.ts │ │ │ │ │ │ │ └── proxy.component.ts │ │ │ │ │ │ └── publish │ │ │ │ │ │ │ ├── batch │ │ │ │ │ │ │ ├── choose-cluster.component.html │ │ │ │ │ │ │ ├── choose-cluster.component.ts │ │ │ │ │ │ │ ├── result.component.html │ │ │ │ │ │ │ └── result.component.ts │ │ │ │ │ │ │ └── single │ │ │ │ │ │ │ ├── publish.component.html │ │ │ │ │ │ │ ├── publish.component.spec.ts │ │ │ │ │ │ │ └── publish.component.ts │ │ │ │ │ ├── api-routing.module.ts │ │ │ │ │ ├── api.module.ts │ │ │ │ │ ├── plugin │ │ │ │ │ │ ├── config │ │ │ │ │ │ │ ├── form │ │ │ │ │ │ │ │ ├── form.component.html │ │ │ │ │ │ │ │ └── form.component.ts │ │ │ │ │ │ │ └── table │ │ │ │ │ │ │ │ ├── table.component.html │ │ │ │ │ │ │ │ └── table.component.ts │ │ │ │ │ │ ├── content │ │ │ │ │ │ │ └── content.component.ts │ │ │ │ │ │ ├── create │ │ │ │ │ │ │ ├── create.component.html │ │ │ │ │ │ │ └── create.component.ts │ │ │ │ │ │ ├── list │ │ │ │ │ │ │ ├── list.component.html │ │ │ │ │ │ │ └── list.component.ts │ │ │ │ │ │ ├── message │ │ │ │ │ │ │ └── message.component.ts │ │ │ │ │ │ ├── plugin.component.ts │ │ │ │ │ │ └── publish │ │ │ │ │ │ │ ├── publish.component.html │ │ │ │ │ │ │ └── publish.component.ts │ │ │ │ │ ├── router.service.ts │ │ │ │ │ ├── router │ │ │ │ │ │ └── router.component.ts │ │ │ │ │ └── types │ │ │ │ │ │ ├── conf.ts │ │ │ │ │ │ └── types.ts │ │ │ │ ├── application │ │ │ │ │ ├── application-routing.module.ts │ │ │ │ │ ├── application.component.ts │ │ │ │ │ ├── application.module.ts │ │ │ │ │ ├── application.service.ts │ │ │ │ │ ├── authentication │ │ │ │ │ │ ├── authentication.component.html │ │ │ │ │ │ ├── authentication.component.ts │ │ │ │ │ │ ├── form │ │ │ │ │ │ │ ├── form.component.html │ │ │ │ │ │ │ └── form.component.ts │ │ │ │ │ │ └── view │ │ │ │ │ │ │ └── view.component.ts │ │ │ │ │ ├── content │ │ │ │ │ │ ├── content.component.html │ │ │ │ │ │ └── content.component.ts │ │ │ │ │ ├── create │ │ │ │ │ │ ├── create.component.html │ │ │ │ │ │ └── create.component.ts │ │ │ │ │ ├── extra │ │ │ │ │ │ ├── extra.component.html │ │ │ │ │ │ ├── extra.component.ts │ │ │ │ │ │ └── form │ │ │ │ │ │ │ ├── form.component.html │ │ │ │ │ │ │ └── form.component.ts │ │ │ │ │ ├── list │ │ │ │ │ │ └── list.component.ts │ │ │ │ │ ├── message │ │ │ │ │ │ ├── message.component.html │ │ │ │ │ │ └── message.component.ts │ │ │ │ │ ├── publish │ │ │ │ │ │ └── publish.component.ts │ │ │ │ │ └── types │ │ │ │ │ │ ├── conf.ts │ │ │ │ │ │ └── types.ts │ │ │ │ ├── audit-log │ │ │ │ │ ├── audit-log-routing.module.ts │ │ │ │ │ ├── audit-log.component.ts │ │ │ │ │ ├── audit-log.module.ts │ │ │ │ │ ├── detail │ │ │ │ │ │ └── detail.component.ts │ │ │ │ │ ├── list │ │ │ │ │ │ ├── list.component.html │ │ │ │ │ │ └── list.component.ts │ │ │ │ │ └── types │ │ │ │ │ │ ├── conf.ts │ │ │ │ │ │ └── types.ts │ │ │ │ ├── auth │ │ │ │ │ ├── activation │ │ │ │ │ │ ├── activation.component.html │ │ │ │ │ │ └── activation.component.ts │ │ │ │ │ ├── info │ │ │ │ │ │ ├── detail │ │ │ │ │ │ │ └── detail.component.ts │ │ │ │ │ │ ├── info.component.html │ │ │ │ │ │ └── info.component.ts │ │ │ │ │ └── update │ │ │ │ │ │ └── update.component.ts │ │ │ │ ├── basic-layout │ │ │ │ │ ├── basic-layout.component.html │ │ │ │ │ ├── basic-layout.component.scss │ │ │ │ │ └── basic-layout.component.ts │ │ │ │ ├── deploy │ │ │ │ │ ├── cluster │ │ │ │ │ │ ├── cert │ │ │ │ │ │ │ ├── cert.component.html │ │ │ │ │ │ │ ├── cert.component.ts │ │ │ │ │ │ │ └── form │ │ │ │ │ │ │ │ ├── form.component.html │ │ │ │ │ │ │ │ └── form.component.ts │ │ │ │ │ │ ├── cluster.component.html │ │ │ │ │ │ ├── cluster.component.ts │ │ │ │ │ │ ├── content │ │ │ │ │ │ │ ├── content.component.html │ │ │ │ │ │ │ └── content.component.ts │ │ │ │ │ │ ├── create │ │ │ │ │ │ │ ├── create.component.html │ │ │ │ │ │ │ └── create.component.ts │ │ │ │ │ │ ├── environment │ │ │ │ │ │ │ ├── config │ │ │ │ │ │ │ │ ├── form │ │ │ │ │ │ │ │ │ └── form.component.ts │ │ │ │ │ │ │ │ └── update │ │ │ │ │ │ │ │ │ └── update.component.ts │ │ │ │ │ │ │ ├── environment.component.html │ │ │ │ │ │ │ ├── environment.component.ts │ │ │ │ │ │ │ ├── history │ │ │ │ │ │ │ │ ├── change │ │ │ │ │ │ │ │ │ └── change.component.ts │ │ │ │ │ │ │ │ └── publish │ │ │ │ │ │ │ │ │ └── publish.component.ts │ │ │ │ │ │ │ └── publish │ │ │ │ │ │ │ │ └── publish.component.ts │ │ │ │ │ │ ├── list │ │ │ │ │ │ │ ├── list.component.html │ │ │ │ │ │ │ └── list.component.ts │ │ │ │ │ │ ├── message │ │ │ │ │ │ │ ├── message.component.html │ │ │ │ │ │ │ └── message.component.ts │ │ │ │ │ │ ├── nodes │ │ │ │ │ │ │ ├── form │ │ │ │ │ │ │ │ └── form.component.ts │ │ │ │ │ │ │ ├── nodes.component.html │ │ │ │ │ │ │ └── nodes.component.ts │ │ │ │ │ │ ├── plugin │ │ │ │ │ │ │ ├── config │ │ │ │ │ │ │ │ ├── config.component.html │ │ │ │ │ │ │ │ └── config.component.ts │ │ │ │ │ │ │ ├── history │ │ │ │ │ │ │ │ ├── change │ │ │ │ │ │ │ │ │ ├── change.component.html │ │ │ │ │ │ │ │ │ └── change.component.ts │ │ │ │ │ │ │ │ └── publish │ │ │ │ │ │ │ │ │ ├── publish.component.html │ │ │ │ │ │ │ │ │ └── publish.component.ts │ │ │ │ │ │ │ ├── plugin.component.html │ │ │ │ │ │ │ ├── plugin.component.ts │ │ │ │ │ │ │ └── publish │ │ │ │ │ │ │ │ └── publish.component.ts │ │ │ │ │ │ └── types │ │ │ │ │ │ │ ├── conf.ts │ │ │ │ │ │ │ └── types.ts │ │ │ │ │ ├── deploy-routing.module.ts │ │ │ │ │ ├── deploy.module.ts │ │ │ │ │ ├── deploy.service.ts │ │ │ │ │ ├── environment │ │ │ │ │ │ ├── create │ │ │ │ │ │ │ ├── create.component.html │ │ │ │ │ │ │ └── create.component.ts │ │ │ │ │ │ ├── detail │ │ │ │ │ │ │ └── detail.component.ts │ │ │ │ │ │ ├── environment.component.ts │ │ │ │ │ │ ├── list │ │ │ │ │ │ │ ├── list.component.html │ │ │ │ │ │ │ └── list.component.ts │ │ │ │ │ │ └── types │ │ │ │ │ │ │ ├── conf.ts │ │ │ │ │ │ │ └── types.ts │ │ │ │ │ └── plugin │ │ │ │ │ │ ├── create │ │ │ │ │ │ ├── create.component.html │ │ │ │ │ │ └── create.component.ts │ │ │ │ │ │ ├── deploy-plugin.component.ts │ │ │ │ │ │ ├── list │ │ │ │ │ │ ├── list.component.html │ │ │ │ │ │ └── list.component.ts │ │ │ │ │ │ ├── message │ │ │ │ │ │ └── message.component.ts │ │ │ │ │ │ └── types │ │ │ │ │ │ ├── conf.ts │ │ │ │ │ │ └── types.ts │ │ │ │ ├── dynamic-demo │ │ │ │ │ └── dynamic-demo.component.ts │ │ │ │ ├── guide │ │ │ │ │ ├── conf.ts │ │ │ │ │ ├── guide.component.html │ │ │ │ │ └── guide.component.ts │ │ │ │ ├── intelligent-plugin │ │ │ │ │ ├── create │ │ │ │ │ │ └── create.component.ts │ │ │ │ │ ├── intelligent-plugin-routing.module.ts │ │ │ │ │ ├── intelligent-plugin.component.ts │ │ │ │ │ ├── intelligent-plugin.module.ts │ │ │ │ │ ├── layout │ │ │ │ │ │ └── layout.component.ts │ │ │ │ │ ├── list │ │ │ │ │ │ └── list.component.ts │ │ │ │ │ └── publish │ │ │ │ │ │ └── publish.component.ts │ │ │ │ ├── layout.module.ts │ │ │ │ ├── local-plugin │ │ │ │ │ └── local-plugin.component.ts │ │ │ │ ├── log-retrieval │ │ │ │ │ ├── conf.ts │ │ │ │ │ ├── log-retrieval-routing.module.ts │ │ │ │ │ ├── log-retrieval.component.html │ │ │ │ │ ├── log-retrieval.component.ts │ │ │ │ │ ├── log-retrieval.module.ts │ │ │ │ │ ├── tail-log │ │ │ │ │ │ └── tail-log.component.ts │ │ │ │ │ └── type.ts │ │ │ │ ├── login │ │ │ │ │ ├── login.component.html │ │ │ │ │ ├── login.component.scss │ │ │ │ │ ├── login.component.ts │ │ │ │ │ ├── logo │ │ │ │ │ │ ├── logo.component.html │ │ │ │ │ │ ├── logo.component.scss │ │ │ │ │ │ └── logo.component.ts │ │ │ │ │ └── password │ │ │ │ │ │ ├── password.component.html │ │ │ │ │ │ ├── password.component.scss │ │ │ │ │ │ └── password.component.ts │ │ │ │ ├── not-found-page │ │ │ │ │ └── not-found-page.component.ts │ │ │ │ ├── plugin │ │ │ │ │ ├── config │ │ │ │ │ │ ├── config.component.html │ │ │ │ │ │ └── config.component.ts │ │ │ │ │ ├── create │ │ │ │ │ │ └── create.component.ts │ │ │ │ │ ├── eo-ng-plugin.service.ts │ │ │ │ │ ├── group │ │ │ │ │ │ ├── group.component.html │ │ │ │ │ │ └── group.component.ts │ │ │ │ │ ├── list │ │ │ │ │ │ ├── list.component.html │ │ │ │ │ │ └── list.component.ts │ │ │ │ │ ├── message │ │ │ │ │ │ ├── message.component.scss │ │ │ │ │ │ └── message.component.ts │ │ │ │ │ ├── plugin-management-routing.module.ts │ │ │ │ │ ├── plugin-management.component.ts │ │ │ │ │ ├── plugin-management.module.ts │ │ │ │ │ └── types │ │ │ │ │ │ ├── conf.ts │ │ │ │ │ │ └── types.ts │ │ │ │ ├── remote-plugin │ │ │ │ │ └── remote-plugin.component.ts │ │ │ │ ├── serv-governance │ │ │ │ │ ├── cache │ │ │ │ │ │ ├── cache.component.ts │ │ │ │ │ │ ├── create │ │ │ │ │ │ │ ├── create.component.html │ │ │ │ │ │ │ └── create.component.ts │ │ │ │ │ │ └── message │ │ │ │ │ │ │ └── message.component.ts │ │ │ │ │ ├── filter │ │ │ │ │ │ ├── footer │ │ │ │ │ │ │ ├── footer.component.html │ │ │ │ │ │ │ └── footer.component.ts │ │ │ │ │ │ ├── form │ │ │ │ │ │ │ ├── form.component.html │ │ │ │ │ │ │ └── form.component.ts │ │ │ │ │ │ ├── serv-governance-filter.service.ts │ │ │ │ │ │ └── table │ │ │ │ │ │ │ ├── table.component.html │ │ │ │ │ │ │ └── table.component.ts │ │ │ │ │ ├── fuse │ │ │ │ │ │ ├── create │ │ │ │ │ │ │ ├── create.component.html │ │ │ │ │ │ │ └── create.component.ts │ │ │ │ │ │ ├── fuse.component.ts │ │ │ │ │ │ └── message │ │ │ │ │ │ │ └── message.component.ts │ │ │ │ │ ├── grey │ │ │ │ │ │ ├── create │ │ │ │ │ │ │ ├── create.component.html │ │ │ │ │ │ │ └── create.component.ts │ │ │ │ │ │ ├── grey.component.ts │ │ │ │ │ │ └── message │ │ │ │ │ │ │ └── message.component.ts │ │ │ │ │ ├── group │ │ │ │ │ │ ├── group.component.html │ │ │ │ │ │ └── group.component.ts │ │ │ │ │ ├── list │ │ │ │ │ │ ├── list.component.html │ │ │ │ │ │ └── list.component.ts │ │ │ │ │ ├── publish │ │ │ │ │ │ └── publish.component.ts │ │ │ │ │ ├── response-form │ │ │ │ │ │ ├── response-form.component.html │ │ │ │ │ │ └── response-form.component.ts │ │ │ │ │ ├── serv-governance-routing.module.ts │ │ │ │ │ ├── serv-governance.module.ts │ │ │ │ │ ├── service-governance.component.ts │ │ │ │ │ ├── service-governance.service.ts │ │ │ │ │ ├── traffic │ │ │ │ │ │ ├── create │ │ │ │ │ │ │ ├── create.component.html │ │ │ │ │ │ │ └── create.component.ts │ │ │ │ │ │ ├── message │ │ │ │ │ │ │ ├── message.component.html │ │ │ │ │ │ │ └── message.component.ts │ │ │ │ │ │ └── traffic.component.ts │ │ │ │ │ ├── types │ │ │ │ │ │ ├── conf.ts │ │ │ │ │ │ └── types.ts │ │ │ │ │ └── visit │ │ │ │ │ │ ├── create │ │ │ │ │ │ ├── create.component.html │ │ │ │ │ │ └── create.component.ts │ │ │ │ │ │ ├── message │ │ │ │ │ │ └── message.component.ts │ │ │ │ │ │ └── visit.component.ts │ │ │ │ └── system │ │ │ │ │ ├── email │ │ │ │ │ ├── config │ │ │ │ │ │ ├── config.component.html │ │ │ │ │ │ └── config.component.ts │ │ │ │ │ └── system-email.component.ts │ │ │ │ │ ├── external-app │ │ │ │ │ ├── create │ │ │ │ │ │ ├── create.component.html │ │ │ │ │ │ └── create.component.ts │ │ │ │ │ ├── external-app.component.ts │ │ │ │ │ ├── list │ │ │ │ │ │ ├── list.component.html │ │ │ │ │ │ └── list.component.ts │ │ │ │ │ └── message │ │ │ │ │ │ └── message.component.ts │ │ │ │ │ ├── system-routing.module.ts │ │ │ │ │ ├── system.component.ts │ │ │ │ │ ├── system.module.ts │ │ │ │ │ ├── types │ │ │ │ │ ├── conf.ts │ │ │ │ │ └── type.ts │ │ │ │ │ └── webhook │ │ │ │ │ ├── config │ │ │ │ │ ├── config.component.html │ │ │ │ │ └── config.component.ts │ │ │ │ │ ├── list │ │ │ │ │ ├── list.component.html │ │ │ │ │ └── list.component.ts │ │ │ │ │ └── webhook.component.ts │ │ │ ├── pipe │ │ │ │ ├── change-word-color.pipe.ts │ │ │ │ └── safe.pipe.ts │ │ │ └── service │ │ │ │ ├── api.service.ts │ │ │ │ ├── auth-guard.service.ts │ │ │ │ ├── base-info.service.ts │ │ │ │ ├── crypto.service.ts │ │ │ │ ├── eo-ng-json.service.ts │ │ │ │ ├── eo-ng-message.service.ts │ │ │ │ ├── eo-ng-navigation.service.ts │ │ │ │ ├── http-interceptors │ │ │ │ ├── error.interceptor.ts │ │ │ │ └── index.ts │ │ │ │ ├── iframe-http.service.ts │ │ │ │ ├── publish-fail.service.ts │ │ │ │ ├── redirect-page.service.ts │ │ │ │ └── websocket.service.ts │ │ │ ├── assets │ │ │ ├── .gitkeep │ │ │ ├── README.md │ │ │ ├── apinto-auth.svg │ │ │ ├── apinto-pro.svg │ │ │ ├── apinto.svg │ │ │ ├── avatar.svg │ │ │ ├── default-guide-icon.png │ │ │ ├── default-navigation-icon.png │ │ │ ├── default-plugin-icon.svg │ │ │ ├── favicon-pro.ico │ │ │ ├── favicon.ico │ │ │ ├── guide.jpg │ │ │ ├── iconpark-apinto.js │ │ │ ├── iconpark.js │ │ │ ├── logo │ │ │ │ ├── logo_dark.png │ │ │ │ └── logo_light.png │ │ │ ├── no-access.svg │ │ │ ├── side_bg.jpg │ │ │ └── theme │ │ │ │ ├── dark.json │ │ │ │ └── light.json │ │ │ ├── environments │ │ │ ├── basic.ts │ │ │ ├── environment.business.prod.ts │ │ │ ├── environment.business.ts │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ │ ├── favicon.ico │ │ │ ├── form.style.scss │ │ │ ├── formily.style.scss │ │ │ ├── index.html │ │ │ ├── input.style.scss │ │ │ ├── layout.style.scss │ │ │ ├── main.ts │ │ │ ├── polyfills.ts │ │ │ ├── select.style.scss │ │ │ ├── styles.scss │ │ │ ├── table.style.scss │ │ │ └── variables.css │ └── eo-ng-apinto-table │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── package.json │ │ ├── src │ │ ├── lib │ │ │ ├── eo-ng-apinto-table.module.ts │ │ │ ├── table │ │ │ │ ├── table.component.html │ │ │ │ └── table.component.ts │ │ │ └── types.ts │ │ └── public-api.ts │ │ ├── tsconfig.json │ │ ├── tsconfig.lib.json │ │ ├── tsconfig.lib.prod.json │ │ └── tsconfig.spec.json ├── proxy.config.demo.json ├── tailwind.config.js ├── test │ └── setup-jest.ts ├── tool │ └── replaceCssVariable.js ├── tsconfig.app.json ├── tsconfig.json └── tsconfig.spec.json ├── go.mod ├── go.sum ├── grpc-service ├── infos.pb.go ├── infos.proto ├── notice_send.pb.go └── notice_send.proto ├── initialize ├── inner-plugin-manager │ ├── embed_plugin.go │ ├── export.go │ ├── interface.go │ └── manager.go ├── navigation.go ├── navigation.yml ├── navigation │ ├── navigation.go │ └── navigation.yml ├── plugin-group │ ├── plugin_group.go │ └── plugin_group.yml ├── plugin_group.go ├── plugin_group.yml ├── plugins.g.go └── plugins │ ├── embed │ ├── api.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ ├── apispace.apinto.com │ │ ├── README.md │ │ ├── apispace.jpg │ │ └── plugin.yml │ ├── application.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ ├── audit.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ ├── cluster.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ ├── discovery.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ ├── email.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ ├── ext_app.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ ├── log.apinto.com │ │ ├── README.md │ │ ├── plugin.yml │ │ └── 日志检索.png │ ├── module_plugin.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ ├── open_api.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ ├── plugin.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ ├── plugin_template.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ ├── strategy-cache.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ ├── strategy-fuse.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ ├── strategy-grey.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ ├── strategy-traffic.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ ├── strategy-visit.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ ├── upstream.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ ├── variable.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ └── webhook.apinto.com │ │ ├── README.md │ │ ├── logo.png │ │ └── plugin.yml │ └── plugins.g.go ├── module ├── access-reader.go ├── builder.go ├── builder_test.go ├── driver.go ├── handler.go ├── middleware-request.go ├── middleware-response.go ├── middleware.go ├── module.go ├── options.go ├── plugin.go ├── provider.go ├── repeat-read.go ├── response-update.go ├── response-update_test.go └── simple.go ├── modules ├── api │ ├── api-dto │ │ └── api.go │ ├── api-entry │ │ ├── api.go │ │ ├── api_history.go │ │ ├── api_runtime.go │ │ ├── api_stat.go │ │ ├── api_version.go │ │ └── publish_history.go │ ├── api.go │ ├── controller │ │ ├── api.go │ │ ├── module.go │ │ ├── options.go │ │ └── routers.go │ ├── driver │ │ ├── api_http.go │ │ ├── api_websocket.go │ │ └── common.go │ ├── mock │ │ └── api_mock.go │ ├── model │ │ └── api.go │ ├── service │ │ ├── api-driver.go │ │ ├── api.go │ │ ├── batch_online_api.go │ │ ├── import_api_data.go │ │ └── init.go │ ├── status-code │ │ └── code.go │ └── store │ │ ├── api.go │ │ ├── api_history.go │ │ ├── api_stat.go │ │ ├── api_version.go │ │ ├── init.go │ │ └── publish_history.go ├── application │ ├── application-controller │ │ ├── application.go │ │ ├── module.go │ │ ├── options.go │ │ └── routers.go │ ├── application-dto │ │ ├── application.go │ │ └── application_auth.go │ ├── application-entry │ │ ├── application.go │ │ ├── application_auth.go │ │ └── application_auth_publish.go │ ├── application-model │ │ ├── application.go │ │ └── application_auth.go │ ├── application-service │ │ ├── application.go │ │ ├── auth.go │ │ ├── driver.go │ │ └── init.go │ ├── application-store │ │ ├── application.go │ │ ├── application_auth.go │ │ ├── application_history.go │ │ ├── application_stat.go │ │ ├── application_version.go │ │ ├── init.go │ │ └── publish_history.go │ ├── application_service.go │ └── driver │ │ ├── aksk.go │ │ ├── apikey.go │ │ ├── basic.go │ │ ├── common.go │ │ └── jwt.go ├── audit │ ├── audit-controller │ │ ├── audit.go │ │ ├── audit_log.go │ │ └── module.go │ ├── audit-entry │ │ └── audit_log.go │ ├── audit-model │ │ ├── audit_log.go │ │ └── operater.go │ ├── audit-service │ │ ├── audit_log.go │ │ └── init.go │ ├── audit-store │ │ ├── audit_log.go │ │ └── init.go │ └── audit.go ├── base │ ├── env-controller │ │ └── enum.go │ ├── env-model │ │ └── cluster_enum.go │ ├── frontend-model │ │ └── frontend.go │ ├── history-entry │ │ └── history.go │ ├── locker-service │ │ ├── init.go │ │ └── lock.go │ ├── namespace-controller │ │ └── namespace.go │ ├── publish-entry │ │ └── publish_history.go │ ├── quote-entry │ │ └── quote.go │ ├── quote-store │ │ ├── init.go │ │ └── quote.go │ ├── random-controller │ │ └── random.go │ ├── runtime-entry │ │ └── runtime.go │ ├── stat-entry │ │ └── stat.go │ └── version-entry │ │ └── version.go ├── cluster │ ├── cluster-controller │ │ ├── cluster.go │ │ ├── cluster_certificate.go │ │ ├── cluster_node.go │ │ └── module.go │ ├── cluster-dto │ │ ├── cluster.go │ │ ├── cluster_certificate.go │ │ ├── cluster_config.go │ │ ├── cluster_node.go │ │ └── cluster_variable.go │ ├── cluster-entry │ │ ├── cluster.go │ │ ├── cluster_certificate.go │ │ ├── cluster_config_runtime.go │ │ └── cluster_node.go │ ├── cluster-mock │ │ └── cluster_mock.go │ ├── cluster-model │ │ ├── cluster.go │ │ ├── cluster_certificate.go │ │ └── cluster_node.go │ ├── cluster-service │ │ ├── apinto_client.go │ │ ├── cluster.go │ │ ├── cluster_certificate.go │ │ ├── cluster_node.go │ │ ├── init.go │ │ └── node_cache.go │ ├── cluster-store │ │ ├── cluster.go │ │ ├── cluster_certificate.go │ │ ├── cluster_history.go │ │ ├── cluster_node.go │ │ ├── cluster_runtime.go │ │ └── init.go │ └── service.go ├── core │ ├── controller │ │ ├── common-strategy.go │ │ ├── env.go │ │ ├── expire.go │ │ ├── frontend.go │ │ ├── module-controller.go │ │ ├── module.go │ │ ├── report.go │ │ ├── session.go │ │ ├── system.go │ │ └── user.go │ ├── model │ │ └── navigation.go │ ├── service.go │ └── service │ │ ├── init.go │ │ ├── navigation.go │ │ ├── provider.go │ │ └── service.go ├── dynamic │ ├── dynamic-controller │ │ ├── define.go │ │ ├── dynamic.go │ │ ├── module.go │ │ ├── options.go │ │ └── provider.go │ ├── dynamic-dto │ │ ├── cluster.go │ │ └── dynamic.go │ ├── dynamic-entry │ │ ├── dynamic.go │ │ ├── dynamic_publish_history.go │ │ ├── dynamic_publish_version.go │ │ ├── dynamic_quote.go │ │ └── sql.sql │ ├── dynamic-model │ │ ├── dynamic.go │ │ └── render.go │ ├── dynamic-service │ │ ├── dynamic.go │ │ ├── init.go │ │ └── variable.go │ ├── dynamic-store │ │ ├── dynamic.go │ │ ├── dynamic_publish_history.go │ │ ├── dynamic_publish_version.go │ │ ├── dynamic_quote.go │ │ └── init.go │ └── dynamic.go ├── email │ ├── controller │ │ ├── email.go │ │ └── module.go │ └── dto │ │ └── email.go ├── group │ ├── group-controller │ │ └── common_group.go │ ├── group-dto │ │ └── common_group.go │ ├── group-entry │ │ └── common_group.go │ ├── group-model │ │ └── common_group.go │ ├── group-service │ │ ├── common_group.go │ │ └── init.go │ ├── group-store │ │ ├── common_group.go │ │ └── init.go │ └── group.go ├── grpc-service │ └── service │ │ ├── cache.go │ │ ├── console_info.go │ │ ├── error.go │ │ ├── init.go │ │ └── notice_send.go ├── log │ ├── dto │ │ ├── arg.go │ │ └── output.go │ └── module │ │ ├── client.go │ │ ├── conn.go │ │ ├── controller.go │ │ ├── download.go │ │ ├── driver.go │ │ ├── module.go │ │ ├── tail.go │ │ └── util.go ├── module-plugin │ ├── controller │ │ ├── module.go │ │ ├── module_plugin.go │ │ └── plugin_front.go │ ├── dto │ │ └── module_plugin.go │ ├── embed_registry │ │ └── embed_plugin.go │ ├── entry │ │ ├── module_plugin.go │ │ ├── module_plugin_enable.go │ │ ├── module_plugin_package.go │ │ └── module_plugin_resources.go │ ├── model │ │ ├── module_plugin.go │ │ ├── plugin_front.go │ │ └── plugin_resources.go │ ├── module_plugin.go │ ├── resources_manager │ │ └── manager.go │ ├── service │ │ ├── common.go │ │ ├── enum.go │ │ ├── error.go │ │ ├── init.go │ │ ├── installed_cache.go │ │ ├── module_plugin.go │ │ ├── module_plugin_service.go │ │ └── navigation_modules_cache.go │ └── store │ │ ├── init.go │ │ ├── module_plugin.go │ │ ├── module_plugin_enable.go │ │ ├── module_plugin_package.go │ │ └── module_plugin_resources.go ├── namespace │ ├── namespace-entry │ │ └── namespace.go │ ├── namespace-mock │ │ └── namespace_mock.go │ ├── namespace-model │ │ └── namespace.go │ ├── namespace-service │ │ ├── init.go │ │ └── namespace.go │ ├── namespace-store │ │ ├── init.go │ │ └── namespace.go │ └── service.go ├── navigation │ ├── navigation-model │ │ └── navigation.go │ ├── navigation-service │ │ ├── init.go │ │ └── navigation.go │ └── navigation.go ├── notice │ ├── controller │ │ ├── notice.go │ │ └── routers.go │ ├── driver.go │ ├── dto │ │ └── notice.go │ ├── notice-entry │ │ └── notice_channel.go │ ├── notice-mock │ │ └── notice_mock.go │ ├── notice-model │ │ └── notice_channel.go │ ├── notice-service │ │ ├── driver.go │ │ ├── init.go │ │ └── notice_channel.go │ ├── notice-store │ │ ├── init.go │ │ ├── notice_channel.go │ │ ├── notice_channel_stat.go │ │ └── notice_channel_version.go │ └── notice.go ├── online │ ├── online-dto │ │ └── common_online.go │ └── service.go ├── openapi │ ├── driver │ │ ├── openAPI3.go │ │ └── swagger2.go │ ├── open-api-controller │ │ ├── api_openAPI.go │ │ ├── module.go │ │ └── routers.go │ ├── openapi-dto │ │ └── api_openAPI.go │ ├── openapi-model │ │ └── api_openAPI.go │ ├── openapi-service │ │ ├── api_openAPI.go │ │ └── init.go │ └── openapi.go ├── openapp │ ├── open-app-controller │ │ ├── external_app.go │ │ ├── module.go │ │ └── routers.go │ ├── open-app-dto │ │ └── external_app.go │ ├── open-app-entry │ │ └── external_app.go │ ├── open-app-model │ │ ├── external-app.go │ │ └── swagger.go │ ├── openapp-service │ │ ├── api_import_format.go │ │ ├── external-app.go │ │ └── init.go │ ├── openapp-store │ │ ├── external_app.go │ │ └── init.go │ └── openapp.go ├── plugin │ ├── cluster_plugin_service.go │ ├── plugin-controller │ │ ├── cluster_plugin.go │ │ ├── module.go │ │ └── plugin.go │ ├── plugin-dto │ │ ├── cluster_plugin.go │ │ └── plugin.go │ ├── plugin-entry │ │ ├── cluster_plugin.go │ │ ├── cluster_plugin_history.go │ │ ├── cluster_plugin_publish_history.go │ │ ├── cluster_plugin_publish_version.go │ │ ├── cluster_plugin_runtime.go │ │ ├── plugin.go │ │ └── plugin_history.go │ ├── plugin-model │ │ ├── cluster_plugin.go │ │ └── plugin.go │ ├── plugin-service │ │ ├── cluster_plugin.go │ │ ├── extender_cache.go │ │ ├── init.go │ │ └── plugin.go │ ├── plugin-store │ │ ├── cluster_plugin.go │ │ ├── cluster_plugin_history.go │ │ ├── cluster_plugin_publish_history.go │ │ ├── cluster_plugin_publish_version.go │ │ ├── cluster_plugin_runtime.go │ │ ├── init.go │ │ ├── plugin.go │ │ └── plugin_history.go │ ├── plugin_service.go │ └── plugin_timer │ │ ├── extender.go │ │ └── init.go ├── plugin_template │ ├── plugin-template-controller │ │ ├── module.go │ │ └── plugin_template.go │ ├── plugin-template-dto │ │ └── plugin_template.go │ ├── plugin-template-entry │ │ ├── plugin_template.go │ │ ├── plugin_template_history.go │ │ ├── plugin_template_runtime.go │ │ ├── plugin_template_stat.go │ │ ├── plugin_template_version.go │ │ └── publish_history.go │ ├── plugin-template-model │ │ └── plugin_template.go │ ├── plugin-template-service │ │ ├── init.go │ │ └── plugin_template.go │ ├── plugin-template-store │ │ ├── init.go │ │ ├── plugin_template.go │ │ ├── plugin_template_history.go │ │ ├── plugin_template_runtime.go │ │ ├── plugin_template_stat.go │ │ ├── plugin_template_version.go │ │ └── publish_history.go │ └── plugin_template_service.go ├── random │ ├── random-service │ │ ├── init.go │ │ └── random.go │ └── random.go ├── remote_storage │ ├── entry │ │ └── remote_key_object.go │ ├── model │ │ └── remote_storage.go │ ├── remote_storage.go │ ├── service │ │ ├── init.go │ │ └── remote_storage.go │ └── store │ │ ├── init.go │ │ └── remote_storage.go ├── strategy │ ├── config │ │ ├── content-type.go │ │ ├── content-type.yml │ │ ├── metrics.go │ │ ├── strategy.go │ │ └── strategy_status.go │ ├── strategy-controller │ │ ├── module-cache.go │ │ ├── module-fuse.go │ │ ├── module-grey.go │ │ ├── module-traffic.go │ │ ├── module-visit.go │ │ ├── stragety-traffic.go │ │ ├── strategy-cache.go │ │ ├── strategy-common.go │ │ ├── strategy-fuse.go │ │ ├── strategy-grey.go │ │ ├── strategy-visit.go │ │ └── strategy.go │ ├── strategy-dto │ │ └── strategy.go │ ├── strategy-entry │ │ ├── strategy.go │ │ ├── strategy_history.go │ │ ├── strategy_publish_history.go │ │ ├── strategy_publish_version.go │ │ ├── strategy_runtime.go │ │ ├── strategy_stat.go │ │ └── strategy_version.go │ ├── strategy-model │ │ └── strategy.go │ ├── strategy-service │ │ ├── filters.go │ │ ├── init.go │ │ ├── strategy-common.go │ │ ├── strategy-handler │ │ │ ├── cache.go │ │ │ ├── check.go │ │ │ ├── fuse.go │ │ │ ├── grey.go │ │ │ ├── traffic.go │ │ │ └── visit.go │ │ └── strategy.go │ ├── strategy-store │ │ ├── init.go │ │ ├── strategy.go │ │ ├── strategy_history.go │ │ ├── strategy_publish_history.go │ │ ├── strategy_publish_version.go │ │ ├── strategy_runtime.go │ │ ├── strategy_stat.go │ │ └── strategy_version.go │ └── strategy.go ├── system │ ├── service │ │ ├── data-key.go │ │ ├── data.go │ │ ├── init.go │ │ └── system.go │ ├── system-entry │ │ └── system_info.go │ ├── system-store │ │ ├── init.go │ │ └── system_info.go │ └── system.go ├── user │ ├── user-dto │ │ ├── access.go │ │ └── user_info.go │ ├── user-entry │ │ └── user_info.go │ ├── user-mock │ │ └── user_mock.go │ ├── user-model │ │ ├── session.go │ │ └── user_info.go │ ├── user-service │ │ ├── init.go │ │ ├── session.go │ │ ├── user_cache.go │ │ └── user_info.go │ ├── user-store │ │ ├── init.go │ │ └── user_info.go │ └── user.go ├── variable │ ├── service.go │ ├── variable-controller │ │ ├── cluster_variable.go │ │ ├── global_variable.go │ │ └── module.go │ ├── variable-dto │ │ └── global_variable.go │ ├── variable-entry │ │ ├── variable_cluster.go │ │ ├── variable_history.go │ │ ├── variable_publish_history.go │ │ ├── variable_runtime.go │ │ ├── variable_version.go │ │ └── variables.go │ ├── variable-model │ │ ├── cluster_variable.go │ │ └── global_variable.go │ ├── variable-service │ │ ├── cluster_variable.go │ │ ├── global_variable.go │ │ └── init.go │ └── variable-store │ │ ├── cluster_variable.go │ │ ├── global_variable.go │ │ ├── init.go │ │ ├── variable_history.go │ │ ├── variable_publish_history.go │ │ ├── variable_publish_version.go │ │ └── variable_runtime.go └── webhook │ ├── controller │ ├── module.go │ └── webhook.go │ └── dto │ └── webhook.go ├── plugin ├── go-plugin │ ├── example │ │ ├── .gitignore │ │ ├── client.go │ │ ├── config.yml │ │ └── plugin │ │ │ ├── .gitignore │ │ │ └── plugin.go │ ├── plugin-client │ │ ├── client.go │ │ └── cmd.go │ ├── plugin │ │ ├── config.go │ │ ├── logger.go │ │ ├── response.go │ │ ├── server.go │ │ └── server_keys.go │ ├── proto │ │ ├── gen.go │ │ ├── plugin.pb.go │ │ ├── plugin.proto │ │ └── plugin_grpc.pb.go │ └── shared │ │ ├── config.go │ │ └── handler.go ├── local │ ├── cmd_unix.go │ ├── cmd_win.go │ ├── config.go │ ├── define.go │ ├── driver.go │ ├── module.go │ ├── plugin.go │ ├── proxy-api.go │ ├── proxy-home.go │ └── proxy-middleware.go └── remote │ ├── config.go │ ├── define.go │ ├── driver.go │ ├── module.go │ ├── plugin.go │ └── remote_apis.go ├── report ├── env.go └── report.go ├── scripts ├── Dockerfile ├── README.md ├── build.sh ├── docker_build.sh ├── docker_publish.sh ├── init.sh ├── prefix.sh └── resource │ ├── config.yml.tpl │ ├── docker_run.sh │ ├── install.sh │ └── run.sh └── store ├── base_history.go ├── base_publish_history.go ├── base_runtime.go ├── basekind.go ├── init.go ├── page.go ├── register.go ├── store.go └── store_mysql └── db-mysql.go /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: APINTO Dashboard Discussion Forum 4 | url: https://github.com/eolinker/apinto-dashboard/discussions 5 | about: Please ask and answer questions here. -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /apinto-dashboard/ 2 | /business/ 3 | *.zip 4 | /work/ 5 | 6 | /batch-publish/ 7 | /migrate/ 8 | -------------------------------------------------------------------------------- /app/apserver/.gitignore: -------------------------------------------------------------------------------- 1 | /apserver 2 | config.yml 3 | config_dev.yml 4 | access.yml 5 | role.yml 6 | apinto_plugin.yml 7 | /config.yml 8 | /apinto_enterprise 9 | work 10 | /plugin/ 11 | *.exe 12 | /local/ 13 | -------------------------------------------------------------------------------- /app/apserver/embed_plugin.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | _ "github.com/eolinker/apinto-dashboard/initialize/navigation" 5 | _ "github.com/eolinker/apinto-dashboard/initialize/plugin-group" 6 | _ "github.com/eolinker/apinto-dashboard/initialize/plugins" 7 | ) 8 | -------------------------------------------------------------------------------- /app/dynamic-module/.gitignore: -------------------------------------------------------------------------------- 1 | *.zip -------------------------------------------------------------------------------- /app/dynamic-module/file-access-log/文件日志.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/app/dynamic-module/file-access-log/文件日志.png -------------------------------------------------------------------------------- /app/dynamic-module/http-access-log/HTTP日志.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/app/dynamic-module/http-access-log/HTTP日志.png -------------------------------------------------------------------------------- /app/dynamic-module/influxdb/InfluxDB配置.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/app/dynamic-module/influxdb/InfluxDB配置.png -------------------------------------------------------------------------------- /app/dynamic-module/influxdb/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | InfluxDB是专门为收集、存储、处理和可视化时间序列数据而构建的平台。时间序列数据是按时间顺序编制索引的一系列数据点。数据点通常由同一来源的连续测量组成,用于跟踪随时间的变化。该插件支持配置InfluxDB v2服务端信息,InfluxDB是监控告警的数据源之一。 3 | ## 功能特性 4 | - 配置InfluxDB v2服务端信息。 5 | - 收集网关请求信息,作为监控告警插件依赖接入,监控告警的数据源之一。 6 | ## 更新日志 7 | ### V1.0(2023-4-30) 8 | - 插件上线 -------------------------------------------------------------------------------- /app/dynamic-module/kafka-access-log/Kafka日志.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/app/dynamic-module/kafka-access-log/Kafka日志.png -------------------------------------------------------------------------------- /app/dynamic-module/nsqd-access-log/NSQ日志.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/app/dynamic-module/nsqd-access-log/NSQ日志.png -------------------------------------------------------------------------------- /app/dynamic-module/package.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ORG_PATH=`pwd` 4 | for file in `ls .` 5 | do 6 | if [[ "$file" == "package.sh" ]];then 7 | continue 8 | fi 9 | cd $ORG_PATH/$file 10 | rm -f *.zip 11 | zip -r -o $file.zip * 12 | done 13 | 14 | cd $ORG_PATH -------------------------------------------------------------------------------- /app/dynamic-module/redis/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | Redis是一个开源(BSD许可)的内存数据结构存储,用作数据库、缓存、消息代理和流媒体引擎。Redis提供数据结构,如字符串、散列、列表、集合、带范围查询的排序集合、位图、超日志、地理空间索引和流。Redis具有内置复制、Lua脚本、LRU驱逐、事务和不同级别的磁盘持久性,并通过Redis Sentinel和Redis Cluster的自动分区提供高可用性。该插件支持配置Redis Cluster信息,从而使Apinto节点接入Redis。 3 | ## 功能特性 4 | - 配置Redis Cluster信息,帮助Apinto节点接入Redis。 5 | - Apinto多个策略、插件依赖Redis,配置Redis后,使用Redis作为缓存数据库。 6 | ## 更新日志 7 | ### V1.0(2023-4-30) 8 | - 插件上线 -------------------------------------------------------------------------------- /app/dynamic-module/redis/Redis配置.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/app/dynamic-module/redis/Redis配置.png -------------------------------------------------------------------------------- /app/dynamic-module/syslog-access-log/SYSLOG日志.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/app/dynamic-module/syslog-access-log/SYSLOG日志.png -------------------------------------------------------------------------------- /client/v1/client_test.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestWorker(t *testing.T) { 9 | 10 | client, err := NewClient([]string{"http://172.27.75.146:9400"}) 11 | 12 | err = client.ForApp().Patch("lGmKT7RvbhCRlhI5", map[string]interface{}{"disable": true}) 13 | fmt.Println(err) 14 | 15 | //key, err := client.ForVariable().GetByKey(namespace, "test1") 16 | //if err != nil { 17 | // panic(err) 18 | //} 19 | //fmt.Println(key) 20 | 21 | //all, err := client.ForVariable().GetAll() 22 | //if err != nil { 23 | // panic(err) 24 | //} 25 | //fmt.Println(all) 26 | 27 | } 28 | -------------------------------------------------------------------------------- /client/v1/initialize/plugin/black_extended.yml: -------------------------------------------------------------------------------- 1 | - 2 | id: eolinker.com:apinto:monitor 3 | name: monitor 4 | status: global 5 | - 6 | id: eolinker.com:apinto:plugin_app 7 | name: app 8 | status: global 9 | - 10 | id: eolinker.com:apinto:strategy-plugin-visit 11 | name: strategy_visit 12 | status: global 13 | - 14 | id: eolinker.com:apinto:strategy-plugin-grey 15 | name: strategy_grey 16 | status: global 17 | - 18 | id: eolinker.com:apinto:strategy-plugin-limiting 19 | name: strategy_limiting 20 | status: global 21 | config: 22 | cache: redis@output 23 | - 24 | id: eolinker.com:apinto:strategy-plugin-fuse 25 | name: strategy_fuse 26 | status: global 27 | config: 28 | cache: redis@output 29 | - 30 | id: eolinker.com:apinto:strategy-plugin-cache 31 | name: strategy_cache 32 | status: global 33 | config: 34 | cache: redis@output -------------------------------------------------------------------------------- /client/v1/initialize/plugin/global.go: -------------------------------------------------------------------------------- 1 | package plugin 2 | 3 | import ( 4 | _ "embed" 5 | 6 | v1 "github.com/eolinker/apinto-dashboard/client/v1" 7 | "gopkg.in/yaml.v3" 8 | ) 9 | 10 | //go:embed apinto_plugin.yml 11 | var pluginData []byte 12 | 13 | var pluginConf []*v1.GlobalPlugin 14 | 15 | func init() { 16 | var err error 17 | 18 | pc := make([]*v1.GlobalPlugin, 0) 19 | err = yaml.Unmarshal(pluginData, &pc) 20 | if err != nil { 21 | panic(err) 22 | } 23 | 24 | pluginConf = pc 25 | } 26 | 27 | func GetGlobalPluginConf() []*v1.GlobalPlugin { 28 | return pluginConf 29 | } 30 | -------------------------------------------------------------------------------- /client/v1/proxy.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | type JsonMarshalProxy []byte 4 | 5 | func (j *JsonMarshalProxy) MarshalJSON() ([]byte, error) { 6 | return *j, nil 7 | } 8 | -------------------------------------------------------------------------------- /client/v2/cluster.go: -------------------------------------------------------------------------------- 1 | package v2 2 | 3 | type Cluster struct { 4 | Cluster string `yaml:"cluster"` 5 | Nodes []*Node `yaml:"nodes"` 6 | } 7 | 8 | type Node struct { 9 | Id string `json:"id"` 10 | Name string `json:"name"` 11 | Peer []string `yaml:"peer"` 12 | Admin []string `json:"admin"` 13 | Server []string `json:"server"` 14 | Leader bool `json:"leader"` 15 | } 16 | -------------------------------------------------------------------------------- /client/v2/status.go: -------------------------------------------------------------------------------- 1 | package v2 2 | 3 | const ( 4 | StatusOffline = "未发布" 5 | StatusPre = "待发布" 6 | StatusOnline = "已发布" 7 | ) 8 | -------------------------------------------------------------------------------- /common/base64.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "encoding/base64" 5 | ) 6 | 7 | //Base64Encode 加密 8 | func Base64Encode(src []byte) string { 9 | return base64.StdEncoding.EncodeToString(src) 10 | } 11 | 12 | //Base64Decode 解密 13 | func Base64Decode(src string) ([]byte, error) { 14 | // 对上面的编码结果进行base64解码 15 | decodeBytes, err := base64.StdEncoding.DecodeString(src) 16 | if err != nil { 17 | return nil, err 18 | } 19 | return decodeBytes, nil 20 | } 21 | -------------------------------------------------------------------------------- /common/const.go: -------------------------------------------------------------------------------- 1 | package common 2 | -------------------------------------------------------------------------------- /common/email.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "crypto/tls" 5 | "gopkg.in/gomail.v2" 6 | ) 7 | 8 | func NewSmtp(host string, port int, protocol string, account string, password string, email string) *Smtp { 9 | d := gomail.NewDialer(host, port, account, password) 10 | if protocol == "ssl" || protocol == "tls" { 11 | d.SSL = true 12 | d.TLSConfig = &tls.Config{ServerName: host} 13 | } 14 | return &Smtp{dialer: d, email: email} 15 | } 16 | 17 | type Smtp struct { 18 | email string 19 | dialer *gomail.Dialer 20 | } 21 | 22 | func (s *Smtp) SendTo(sends []string, title, msg string) error { 23 | 24 | m := gomail.NewMessage() 25 | m.SetHeader("From", s.email) 26 | m.SetHeader("To", sends...) 27 | m.SetHeader("Subject", title) 28 | m.SetBody("text/html;charset=utf-8", msg) 29 | 30 | return s.dialer.DialAndSend(m) 31 | } 32 | -------------------------------------------------------------------------------- /common/error.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "errors" 5 | "strings" 6 | ) 7 | 8 | var ( 9 | ClusterNotExist = errors.New("cluster does not exist") 10 | ) 11 | 12 | const workerNotExistErrStr = "worker-data not exits" 13 | 14 | // CheckWorkerNotExist 检查报错信息是否为worker实例不存在 15 | func CheckWorkerNotExist(err error) error { 16 | if err != nil && strings.Contains(err.Error(), workerNotExistErrStr) { 17 | return nil 18 | } 19 | return err 20 | } 21 | -------------------------------------------------------------------------------- /common/float64.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | ) 7 | 8 | // FormatFloat64 float64保留places位小数 9 | func FormatFloat64(f float64, places int) float64 { 10 | formatStr := "%." + strconv.Itoa(places) + "f" 11 | f64, _ := strconv.ParseFloat(fmt.Sprintf(formatStr, f), 64) 12 | return f64 13 | } 14 | -------------------------------------------------------------------------------- /common/http.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "io" 5 | "net/http" 6 | "strings" 7 | ) 8 | 9 | // NewRequest body = strings.NewReader(string(by)) 10 | func NewRequest(method, url string, body io.Reader) (by []byte, err error) { 11 | method = strings.ToUpper(method) 12 | client := &http.Client{} 13 | req, err := http.NewRequest(method, url, body) 14 | req.Header.Add("Content-Type", "application/json;charset=UTF-8") 15 | defer req.Body.Close() 16 | if err != nil { 17 | return nil, err 18 | } 19 | resp, err := client.Do(req) 20 | if err != nil { 21 | return nil, err 22 | } 23 | defer resp.Body.Close() 24 | return io.ReadAll(resp.Body) 25 | } 26 | -------------------------------------------------------------------------------- /common/json.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "github.com/xeipuuv/gojsonschema" 7 | "io" 8 | ) 9 | 10 | func DecodeJSON(r io.Reader, obj any) error { 11 | decoder := json.NewDecoder(r) 12 | return decoder.Decode(obj) 13 | } 14 | 15 | func JsonSchemaValid(schema, data string) error { 16 | // 解析JSON Schema 17 | loader := gojsonschema.NewStringLoader(schema) 18 | schemaDocument, err := gojsonschema.NewSchema(loader) 19 | if err != nil { 20 | return err 21 | } 22 | 23 | // 解析待校验的JSON数据 24 | documentLoader := gojsonschema.NewStringLoader(data) 25 | result, err := schemaDocument.Validate(documentLoader) 26 | if err != nil { 27 | return err 28 | } 29 | if result.Valid() { 30 | return nil 31 | } 32 | return errors.New(result.Errors()[0].String()) 33 | } 34 | -------------------------------------------------------------------------------- /common/map.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | type Map map[string]any 4 | -------------------------------------------------------------------------------- /common/md5.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "crypto/md5" 5 | "encoding/hex" 6 | ) 7 | 8 | func Md5(str string) string { 9 | h := md5.New() 10 | h.Write([]byte(str)) 11 | return hex.EncodeToString(h.Sum(nil)) 12 | } 13 | -------------------------------------------------------------------------------- /common/panic.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "runtime" 7 | ) 8 | 9 | func PanicTrace(err interface{}) string { 10 | buf := new(bytes.Buffer) 11 | _, _ = fmt.Fprintf(buf, "%v\n", err) 12 | for i := 1; ; i++ { 13 | pc, file, line, ok := runtime.Caller(i) 14 | if !ok { 15 | break 16 | } 17 | _, _ = fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc) 18 | } 19 | return buf.String() 20 | } 21 | -------------------------------------------------------------------------------- /common/path.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "errors" 5 | "net/url" 6 | "os" 7 | "path/filepath" 8 | "strings" 9 | ) 10 | 11 | func CheckAndFormatPath(path string) (string, error) { 12 | decodedPath, err := url.PathUnescape(path) 13 | if err != nil { 14 | return path, errors.New("Unescape fail. ") 15 | } 16 | if CheckPathContainsIPPort(decodedPath) { 17 | return path, errors.New("path is illegal. ") 18 | } 19 | if idx := strings.Index(decodedPath, "?"); idx != -1 { 20 | return path, errors.New("can't contain ?. ") 21 | } 22 | return decodedPath, nil 23 | } 24 | 25 | func GetCurrentPath() (string, error) { 26 | execPath, err := os.Executable() 27 | if err != nil { 28 | return "", err 29 | } 30 | currentPath, err := filepath.EvalSymlinks(filepath.Dir(execPath)) 31 | if err != nil { 32 | return "", err 33 | } 34 | return currentPath, nil 35 | } 36 | -------------------------------------------------------------------------------- /common/restful/builder.go: -------------------------------------------------------------------------------- 1 | package restful 2 | 3 | import ( 4 | "net/http" 5 | "net/url" 6 | ) 7 | 8 | type requestCore struct { 9 | *builderCore 10 | header http.Header 11 | query url.Values 12 | } 13 | 14 | type builderCore struct { 15 | Config 16 | path PathGen 17 | method string 18 | } 19 | 20 | func newBuilderCore(config Config, method string, path string) builderCore { 21 | return builderCore{Config: config, path: createPath(path), method: method} 22 | } 23 | 24 | func (b *builderCore) build() *requestCore { 25 | 26 | return &requestCore{builderCore: b, header: b.header.Clone(), query: cloneValues(b.query)} 27 | 28 | } 29 | func (b *builderCore) Reset(c Config) { 30 | b.Config = c 31 | } 32 | -------------------------------------------------------------------------------- /common/restful/data.go: -------------------------------------------------------------------------------- 1 | package restful 2 | 3 | type ResponseData[D any] struct { 4 | Code int `json:"code,omitempty"` 5 | Message string `json:"message,omitempty"` 6 | RequestId string `json:"requestId,omitempty"` 7 | Success bool `json:"success,omitempty"` 8 | Data *D `json:"data"` 9 | } 10 | type Response struct { 11 | Code int `json:"code,omitempty"` 12 | Message string `json:"message,omitempty"` 13 | RequestId string `json:"requestId,omitempty"` 14 | Success bool `json:"success,omitempty"` 15 | } 16 | -------------------------------------------------------------------------------- /common/slice.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | // ListPage 返回截取下标 [i:y] 4 | // 5 | // if i == 0 && y == 0 { 6 | // "分页错误" 7 | // } 8 | // list[i:y] 9 | func ListPage(pageNo, pageSize int, length int) (int, int) { 10 | if pageNo == 0 { 11 | pageNo = 1 12 | } 13 | if (pageNo-1)*pageSize > length { 14 | return 0, 0 15 | } 16 | if pageNo == 1 { 17 | if pageNo*pageSize > length { 18 | return 0, (pageSize * pageNo) - ((pageSize * pageNo) - length) 19 | } 20 | return 0, pageSize * pageNo 21 | } else { 22 | if pageNo*pageSize > length { 23 | return pageSize * (pageNo - 1), (pageSize * pageNo) - ((pageSize * pageNo) - length) 24 | } else { 25 | return pageSize * (pageNo - 1), pageSize * pageNo 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /common/time.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import "time" 4 | 5 | const formatTime = "2006-01-02 15:04:05" 6 | 7 | func TimeToStr(t time.Time) string { 8 | if t.IsZero() { 9 | return "-" 10 | } 11 | return t.Format(formatTime) 12 | } 13 | 14 | func StrToTime(t string) time.Time { 15 | location, _ := time.ParseInLocation(formatTime, t, time.Local) 16 | return location 17 | } 18 | 19 | func GenVersion(now time.Time) string { 20 | return now.Format("20060102150405") 21 | } 22 | -------------------------------------------------------------------------------- /common/yml.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "gopkg.in/yaml.v3" 5 | io "io" 6 | ) 7 | 8 | func DecodeYAML(r io.Reader, obj any) error { 9 | decoder := yaml.NewDecoder(r) 10 | return decoder.Decode(obj) 11 | } 12 | -------------------------------------------------------------------------------- /config/dir.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | ) 7 | 8 | //GetLastAbsPathByExecutable 获取执行程序所在的上一层级目录的绝对路径 9 | func GetLastAbsPathByExecutable() (string, error) { 10 | exePath, err := os.Executable() 11 | if err != nil { 12 | return "", err 13 | } 14 | res, _ := filepath.EvalSymlinks(exePath) 15 | res = filepath.Dir(res) //获取程序所在目录 16 | res = filepath.Dir(res) //获取程序所在上一层级目录 17 | return res, nil 18 | } 19 | -------------------------------------------------------------------------------- /config/redis.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "github.com/eolinker/apinto-dashboard/cache" 8 | "github.com/redis/go-redis/v9" 9 | ) 10 | 11 | func InitRedis() { 12 | 13 | client := redis.NewClusterClient(&redis.ClusterOptions{ 14 | Addrs: getRedisAddr(), 15 | Username: getRedisUserName(), 16 | Password: getRedisPwd(), 17 | }) 18 | 19 | timeout, cancelFunc := context.WithTimeout(context.Background(), time.Second) 20 | defer cancelFunc() 21 | if err := client.Ping(timeout).Err(); err != nil { 22 | _ = client.Close() 23 | panic(err) 24 | } 25 | 26 | cache.InitCache(client) 27 | } 28 | -------------------------------------------------------------------------------- /config/store.go: -------------------------------------------------------------------------------- 1 | //go:build !mysql 2 | // +build !mysql 3 | 4 | package config 5 | 6 | func InitDb() { 7 | return 8 | } 9 | -------------------------------------------------------------------------------- /controller/.gitignore: -------------------------------------------------------------------------------- 1 | /dist/ -------------------------------------------------------------------------------- /controller/audit.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | audit_model "github.com/eolinker/apinto-dashboard/modules/audit/audit-model" 5 | "github.com/gin-gonic/gin" 6 | ) 7 | 8 | type LogOperateType audit_model.LogOperateType 9 | 10 | func (l LogOperateType) Handler(ginCtx *gin.Context) { 11 | ginCtx.Set(Operate, int(l)) 12 | } 13 | -------------------------------------------------------------------------------- /controller/gin_context.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "github.com/gin-gonic/gin" 7 | ) 8 | 9 | func SetGinContextAuditObject(ctx context.Context, v interface{}) { 10 | if ginCtx, ok := ctx.(*gin.Context); ok { 11 | objectData, _ := json.Marshal(v) 12 | ginCtx.Set(AuditObject, string(objectData)) 13 | 14 | } 15 | 16 | } 17 | 18 | func GetGinContextAuditObject(ginCtx *gin.Context) (value any, exists bool) { 19 | 20 | return ginCtx.Get(AuditObject) 21 | 22 | } 23 | 24 | func GetNamespaceId(ginCtx *gin.Context) int { 25 | id := ginCtx.GetInt(NamespaceId) 26 | if id == 0 { 27 | return 1 28 | } 29 | return id 30 | } 31 | -------------------------------------------------------------------------------- /controller/users/user.go: -------------------------------------------------------------------------------- 1 | package users 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/controller" 5 | "github.com/eolinker/apinto-dashboard/modules/user" 6 | "github.com/eolinker/eosc/common/bean" 7 | "github.com/gin-gonic/gin" 8 | ) 9 | 10 | const ( 11 | userIdKey = "userId" 12 | ) 13 | 14 | var ( 15 | userInfoService user.IUserInfoService 16 | ) 17 | 18 | func init() { 19 | bean.Autowired(&userInfoService) 20 | } 21 | func GetUserId(ginCtx *gin.Context) int { 22 | 23 | id := ginCtx.GetInt(userIdKey) 24 | if id != 0 { 25 | return id 26 | } 27 | 28 | userName := ginCtx.GetString(controller.UserName) 29 | if userName == "" { 30 | return 0 31 | } 32 | userInfo, err := userInfoService.GetUserInfoByName(ginCtx, userName) 33 | if err != nil { 34 | return 0 35 | } 36 | ginCtx.Set(userIdKey, userInfo.Id) 37 | return userInfo.Id 38 | 39 | } 40 | -------------------------------------------------------------------------------- /enum/cluster_config.go: -------------------------------------------------------------------------------- 1 | package enum 2 | -------------------------------------------------------------------------------- /enum/cluster_node_status.go: -------------------------------------------------------------------------------- 1 | package enum 2 | 3 | import "fmt" 4 | 5 | type ClusterNodeStatus int 6 | 7 | const ( 8 | ClusterNodeStatusNone = iota 9 | ClusterNodeStatusNotRunning 10 | ClusterNodeStatusRunning 11 | ClusterNodeStatusAll 12 | ) 13 | 14 | var ( 15 | clusterNodeStatusNames = map[ClusterNodeStatus]string{ 16 | ClusterNodeStatusNone: "NONE", 17 | ClusterNodeStatusNotRunning: "NOTRUNNING", //未运行 18 | ClusterNodeStatusRunning: "RUNNING", //运行中 19 | } 20 | ) 21 | 22 | func (e ClusterNodeStatus) MarshalJSON() ([]byte, error) { 23 | return []byte(fmt.Sprint("\"", e.String(), "\"")), nil 24 | } 25 | 26 | func (e ClusterNodeStatus) String() string { 27 | if e >= ClusterNodeStatusAll { 28 | return "unknown" 29 | } 30 | return clusterNodeStatusNames[e] 31 | } 32 | -------------------------------------------------------------------------------- /enum/cluster_status.go: -------------------------------------------------------------------------------- 1 | package enum 2 | 3 | import "fmt" 4 | 5 | type ClusterStatus int 6 | 7 | const ( 8 | ClusterStatusNone = iota 9 | ClusterStatusNormal 10 | ClusterStatusPartiallyNormal 11 | ClusterStatusAbnormal 12 | ClusterStatusAbnormalAll 13 | ) 14 | 15 | var ( 16 | clusterStatusNames = map[ClusterStatus]string{ 17 | ClusterStatusNone: "NONE", 18 | ClusterStatusNormal: "NORMAL", 19 | ClusterStatusPartiallyNormal: "PARTIALLY_NORMAL", 20 | ClusterStatusAbnormal: "ABNORMAL", 21 | } 22 | clusterStatusIndex = map[string]ClusterStatus{} 23 | ) 24 | 25 | func (e ClusterStatus) MarshalJSON() ([]byte, error) { 26 | return []byte(fmt.Sprint("\"", e.String(), "\"")), nil 27 | } 28 | 29 | func (e ClusterStatus) String() string { 30 | if e >= ClusterStatusAbnormalAll { 31 | return "unknown" 32 | } 33 | return clusterStatusNames[e] 34 | } 35 | -------------------------------------------------------------------------------- /enum/common.go: -------------------------------------------------------------------------------- 1 | package enum 2 | 3 | const ( 4 | HttpALL = "ALL" 5 | HttpGET = "GET" 6 | HttpPOST = "POST" 7 | HttpPUT = "PUT" 8 | HttpDELETE = "DELETE" 9 | HttpPATCH = "PATCH" 10 | HttpHEADER = "HEADER" 11 | HttpOPTIONS = "OPTIONS" 12 | ) 13 | -------------------------------------------------------------------------------- /enum/keyword.go: -------------------------------------------------------------------------------- 1 | package enum 2 | 3 | import "github.com/eolinker/apinto-dashboard/modules/strategy/config" 4 | 5 | var Keyword = map[string]struct{}{config.FilterValuesALL: {}, config.FilterApplication: {}, config.FilterApi: {}, config.FilterPath: {}, config.FilterService: {}, config.FilterMethod: {}, config.FilterIP: {}} 6 | -------------------------------------------------------------------------------- /frontend/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2021: true 5 | }, 6 | extends: ['standard'], 7 | parser: '@typescript-eslint/parser', 8 | parserOptions: { 9 | ecmaVersion: 12, 10 | sourceType: 'module' 11 | }, 12 | plugins: ['@typescript-eslint'], 13 | rules: { 14 | 'no-unused-vars': 'off', 15 | '@typescript-eslint/no-unused-vars': 2, 16 | 'no-useless-constructor': 'off', 17 | '@typescript-eslint/no-useless-constructor': 'warn' 18 | }, 19 | globals: { 20 | angular: true, 21 | page: true, 22 | describe: true, 23 | it: true, 24 | test: true, 25 | expect: true, 26 | beforeEach: true, 27 | jest: true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /frontend/.npmrc: -------------------------------------------------------------------------------- 1 | save=true 2 | save-exact=true 3 | registry=https://registry.npmmirror.com 4 | -------------------------------------------------------------------------------- /frontend/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "semi": false, 4 | "trailingComma": "none", 5 | "bracketSpacing": true 6 | } -------------------------------------------------------------------------------- /frontend/.yarnrc: -------------------------------------------------------------------------------- 1 | save=true 2 | save-exact=true 3 | registry=https://registry.npmmirror.com 4 | -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 | # Apinto 2 | 3 | ## 从npm切换成yarn(首次切换需要,切换后请直接从安装依赖开始 4 | `npm install yarn -g ` 安装yarn 5 | 6 | `yarn versions` 验证yarn版本,确认是否安装好 7 | 8 | `rm -rf node_modules` 删除原先的node_modules文件 9 | 10 | `yarn` 重新安装,此处可能要求选择eo-ng*依赖包的版本,可以直接用enter键选择最新版本 11 | 12 | `yarn run dll` 重新编译dll,此处可能出现找不到的报错,可以略过 13 | 14 | `yarn run deploy` 此处可能出现找不到的报错,可以略过 15 | 16 | `yarn config set registry https://registry.npm.taobao.org` 将安装源切换为淘宝镜像源,会快一些 17 | 18 | ## 安装依赖 19 | `yarn install --legacy-peer-deps` 20 | 21 | ## 打包 22 | `yarn build` 23 | 24 | ## 本地运行 25 | 如需本地单独运行前端项目, 26 | 27 | 1. 先移除frontend文件夹根路径的.angular.json文件里的deployUrl配置(如与apinto网关一同运行,则需要恢复该配置) 28 | 29 | 2. 运行 `yarn start:demo`,该命令将为您在本地运行前端项目,其中请求接口将通过代理连接到 demo-dashboard.apinto.com, 账号信息可查看apinto项目的readme文档 30 | 31 | 3. 如您已自行部署好apinto后端,可以通过修改proxy.config.demo.json文件里的地址,将请求接口地址改成后端部署地址;如不需要代理,可删除package.json文件中,`yarn start:demo`语句里的代理配置 -------------------------------------------------------------------------------- /frontend/projects/core/src/app/component/iframe/iframe.component.html: -------------------------------------------------------------------------------- 1 | 2 |
7 |
8 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/component/intelligent-plugin/create/create.component.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/component/intelligent-plugin/layout/layout.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/component/intelligent-plugin/layout/layout.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | @Component({ 3 | selector: 'eo-ng-intelligent-plugin-layout', 4 | templateUrl: './layout.component.html', 5 | styles: [ 6 | ] 7 | }) 8 | export class EoIntelligentPluginLayoutComponent { 9 | } 10 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/component/intelligent-plugin/types/conf.ts: -------------------------------------------------------------------------------- 1 | import { THEAD_TYPE } from 'eo-ng-table' 2 | 3 | export const EoIntelligentPluginDefaultThead:THEAD_TYPE[] = [ 4 | { 5 | title: '名称', 6 | left: true 7 | }, 8 | { title: 'ID' }, 9 | { title: '描述' }, 10 | { title: '状态' }, 11 | { title: '更新人' }, 12 | { title: '更新时间' }, 13 | { 14 | title: '操作', 15 | right: true 16 | } 17 | ] 18 | 19 | export const PublishTableHeadName:THEAD_TYPE[] = [ 20 | { type: 'checkbox' }, 21 | { title: '集群' }, 22 | { title: '状态' }, 23 | { title: '更新人' }, 24 | { title: '更新时间' } 25 | ] 26 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/component/user-avatar/user-avatar.component.html: -------------------------------------------------------------------------------- 1 |
2 | 7 |
8 | 9 |
10 |
11 | 用户头像 12 | {{ nickName }} 13 |
14 |
15 |
16 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/component/user-avatar/user-avatar.component.scss: -------------------------------------------------------------------------------- 1 | :host ::ng-deep { 2 | eo-ng-dropdown button { 3 | border: none !important; 4 | background-color: transparent !important; 5 | width: auto; 6 | height: 28px !important; 7 | line-height: 28px !important; 8 | } 9 | 10 | .name-width { 11 | height: 0; 12 | margin-left: 48px; 13 | } 14 | 15 | .avatar { 16 | color: var(--MAIN_THEME_BG); 17 | } 18 | 19 | .iconfont { 20 | font-size: 32px; 21 | color: #dadadb; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/constant/form.ts: -------------------------------------------------------------------------------- 1 | // 表单的常用方法 2 | import { FormGroup } from '@angular/forms' 3 | // 表单初始化 4 | 5 | // 表单赋值 6 | export function setFormValue (form:FormGroup, data:{[key:string]:any}):void { 7 | Object.keys(form.controls).forEach(key => { 8 | if (form.controls[key] instanceof FormGroup) { 9 | setFormValue(form.controls[key] as FormGroup, data[key]) 10 | } else { 11 | form.controls[key].setValue(data[key]) 12 | } 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/custom-preloading-strategy.ts: -------------------------------------------------------------------------------- 1 | import { PreloadingStrategy, Route } from '@angular/router' 2 | import { Observable, of, delay, mergeMap } from 'rxjs' 3 | 4 | export class CustomPreloadingStrategy implements PreloadingStrategy { 5 | preload (route:Route, fn:()=> Observable): Observable { 6 | return of(true).pipe( 7 | delay(1000), 8 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 9 | mergeMap((_: boolean) => fn()) 10 | ) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/directive/auto-focus.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, ElementRef } from '@angular/core' 2 | 3 | @Directive({ 4 | selector: '[eoNgAutoFocus]' 5 | }) 6 | export class AutoFocusDirective { 7 | constructor ( 8 | private el:ElementRef) { } 9 | 10 | ngAfterViewInit ():void { 11 | setTimeout( 12 | () => { 13 | this.el.nativeElement.focus() 14 | }, 0 15 | ) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/directive/directive.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core' 2 | import { CommonModule } from '@angular/common' 3 | import { UserAccessDirective } from './user-access.directive' 4 | import { TreeDragDirective } from './tree-drag.directive' 5 | import { RowExpandButtonDirective } from './row-expand-button.directive' 6 | import { AutoFocusDirective } from './auto-focus.directive' 7 | import { EoNgScrollDomDirective } from './eo-ng-scroll-dom.directive' 8 | 9 | @NgModule({ 10 | declarations: [UserAccessDirective, TreeDragDirective, RowExpandButtonDirective, AutoFocusDirective, EoNgScrollDomDirective], 11 | imports: [ 12 | CommonModule 13 | ], 14 | exports: [ 15 | UserAccessDirective, TreeDragDirective, 16 | RowExpandButtonDirective, AutoFocusDirective, 17 | EoNgScrollDomDirective 18 | ] 19 | }) 20 | export class DirectiveModule { } 21 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/api/api-list/message/http-message/http-message.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | import { ApiMessageComponent } from '../message.component' 3 | 4 | @Component({ 5 | selector: 'eo-ng-api-http-message', 6 | template: ` 7 | 8 | `, 9 | styles: [ 10 | ] 11 | }) 12 | export class ApiHttpMessageComponent extends ApiMessageComponent { 13 | } 14 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/api/api-list/message/websocket-message/websocket-message.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | import { ApiMessageComponent } from '../message.component' 3 | 4 | @Component({ 5 | selector: 'eo-ng-api-websocket-message', 6 | template: ` 7 | 8 | 9 | `, 10 | styles: [ 11 | ] 12 | }) 13 | export class ApiWebsocketMessageComponent extends ApiMessageComponent { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/api/api-list/publish/batch/result.component.html: -------------------------------------------------------------------------------- 1 |
2 | 12 | 13 | 14 | 18 | 19 |
20 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/api/plugin/list/list.component.html: -------------------------------------------------------------------------------- 1 |
2 |
5 | 14 |
15 |
16 | 23 | 24 |
25 |
26 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/api/plugin/plugin.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | 3 | @Component({ 4 | selector: 'eo-ng-api-plugin-template', 5 | template: ` 6 | `, 7 | styles: [ 8 | ] 9 | }) 10 | export class ApiPluginTemplateComponent { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/api/plugin/publish/publish.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 13 | 14 |
15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/api/router/router.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | 3 | @Component({ 4 | selector: 'app-router', 5 | template: ` 6 | 7 | `, 8 | styles: [ 9 | ] 10 | }) 11 | export class RouterComponent { 12 | } 13 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/application/application.component.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: MengjieYang yangmengjie@eolink.com 3 | * @Date: 2022-08-17 23:42:52 4 | * @LastEditors: MengjieYang yangmengjie@eolink.com 5 | * @LastEditTime: 2022-08-24 00:34:31 6 | * @FilePath: /apinto/src/app/layout/application/application-management/application-management.component.ts 7 | * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE 8 | */ 9 | import { Component } from '@angular/core' 10 | @Component({ 11 | selector: 'app-application-management', 12 | template: ` 13 | 14 | `, 15 | styles: [ 16 | ` 17 | :host{ 18 | height:100%; 19 | display:block; 20 | }` 21 | ] 22 | }) 23 | export class ApplicationManagementComponent { 24 | } 25 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/application/message/message.component.html: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/audit-log/audit-log-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core' 2 | import { RouterModule, Routes } from '@angular/router' 3 | import { AuditLogComponent } from './audit-log.component' 4 | import { AuditLogListComponent } from './list/list.component' 5 | 6 | const routes: Routes = [{ 7 | path: '', 8 | component: AuditLogComponent, 9 | data: { id: '7' }, 10 | children: [ 11 | { 12 | path: '', 13 | component: AuditLogListComponent 14 | } 15 | ] 16 | }] 17 | 18 | @NgModule({ 19 | imports: [RouterModule.forChild(routes)], 20 | exports: [RouterModule] 21 | }) 22 | export class AuditLogRoutingModule { } 23 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/audit-log/audit-log.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | 3 | @Component({ 4 | selector: 'eo-ng-audit-log', 5 | template: ` 6 | 7 | `, 8 | styles: [ 9 | ] 10 | }) 11 | export class AuditLogComponent { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/audit-log/types/types.ts: -------------------------------------------------------------------------------- 1 | import { Operator } from '../../../constant/type' 2 | export interface AuditLogDetail{ 3 | attr:string 4 | value:string 5 | } 6 | 7 | export interface AuditLogsData{ 8 | id:number, 9 | operator:Operator, 10 | operateType: string, 11 | kind:string, 12 | time:string 13 | ip:string, 14 | [k:string]:any 15 | } 16 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/auth/update/update.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | 3 | @Component({ 4 | selector: 'eo-ng-auth-update', 5 | template: ` 6 | `, 7 | styles: [ 8 | ] 9 | }) 10 | export class AuthUpdateComponent {} 11 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/deploy/cluster/cluster.component.html: -------------------------------------------------------------------------------- 1 | 9 | 10 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/deploy/cluster/cluster.component.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: MengjieYang yangmengjie@eolink.com 3 | * @Date: 2022-07-20 00:02:55 4 | * @LastEditors: MengjieYang yangmengjie@eolink.com 5 | * @LastEditTime: 2022-07-20 23:27:14 6 | * @FilePath: /apinto/src/app/layout/deploy-cluster/deploy-cluster.component.ts 7 | * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE 8 | */ 9 | import { Component } from '@angular/core' 10 | 11 | @Component({ 12 | selector: 'eo-ng-deploy-cluster', 13 | templateUrl: './cluster.component.html', 14 | styles: [ 15 | ] 16 | }) 17 | export class DeployClusterComponent { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/deploy/cluster/plugin/history/change/change.component.html: -------------------------------------------------------------------------------- 1 |
2 | 18 | 19 |
20 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/deploy/environment/environment.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | 3 | @Component({ 4 | selector: 'eo-ng-deploy-environment', 5 | template: ` 6 | 7 | `, 8 | styles: [ 9 | '' 10 | ] 11 | }) 12 | export class DeployEnvironmentComponent { 13 | } 14 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/deploy/environment/types/types.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/frontend/projects/core/src/app/layout/deploy/environment/types/types.ts -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/deploy/plugin/deploy-plugin.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | 3 | @Component({ 4 | selector: 'eo-ng-deploy-plugin', 5 | template: ` 6 | 7 | `, 8 | styles: [ 9 | ] 10 | }) 11 | export class DeployPluginComponent { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/deploy/plugin/types/conf.ts: -------------------------------------------------------------------------------- 1 | import { THEAD_TYPE } from 'eo-ng-table' 2 | 3 | export const PluginsTableHeadName: THEAD_TYPE[] = [ 4 | { 5 | type: 'sort', 6 | width: 40 7 | }, 8 | { title: '插件名称' }, 9 | { title: '扩展ID' }, 10 | { title: '描述' }, 11 | { title: '更新时间' }, 12 | { 13 | title: '操作', 14 | right: true 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/deploy/plugin/types/types.ts: -------------------------------------------------------------------------------- 1 | // 插件管理列表 2 | export type PluginItem = { 3 | name:string 4 | extended:string 5 | desc:string 6 | updateTime:string 7 | operator:string 8 | isDelete:boolean 9 | isBuilt:boolean 10 | } 11 | 12 | // 插件管理编辑 13 | export type PluginData = { 14 | name:string 15 | rely:string 16 | extended:string 17 | desc:string 18 | } 19 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/dynamic-demo/dynamic-demo.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | 3 | @Component({ 4 | selector: 'eo-ng-dynamic-demo', 5 | template: ` 6 | 7 | 8 | `, 9 | styles: [ 10 | ] 11 | }) 12 | export class DynamicDemoComponent { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/intelligent-plugin/create/create.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | import { EoIntelligentPluginCreateComponent } from '../../../component/intelligent-plugin/create/create.component' 3 | 4 | @Component({ 5 | selector: 'eo-ng-intelligent-plugin-create', 6 | templateUrl: '../../../component/intelligent-plugin/create/create.component.html', 7 | styles: [ 8 | ] 9 | }) 10 | export class IntelligentPluginCreateComponent extends EoIntelligentPluginCreateComponent { 11 | } 12 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/intelligent-plugin/intelligent-plugin-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core' 2 | import { RouterModule, Routes } from '@angular/router' 3 | import { IntelligentPluginComponent } from './intelligent-plugin.component' 4 | import { IntelligentPluginLayoutComponent } from './layout/layout.component' 5 | 6 | const routes: Routes = [{ 7 | path: '', 8 | component: IntelligentPluginComponent, 9 | children: [ 10 | { 11 | path: ':moduleName', 12 | children: [{ 13 | path: '**', 14 | component: IntelligentPluginLayoutComponent 15 | } 16 | ] 17 | } 18 | ] 19 | }] 20 | 21 | @NgModule({ 22 | imports: [RouterModule.forChild(routes)], 23 | exports: [RouterModule] 24 | }) 25 | export class IntelligentPluginRoutingModule { } 26 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/intelligent-plugin/intelligent-plugin.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | 3 | @Component({ 4 | selector: 'eo-ng-intelligent-plugin', 5 | template: ` 6 | 7 | `, 8 | styles: [ 9 | ] 10 | }) 11 | export class IntelligentPluginComponent { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/intelligent-plugin/layout/layout.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | import { EoIntelligentPluginLayoutComponent } from '../../../component/intelligent-plugin/layout/layout.component' 3 | @Component({ 4 | selector: 'eo-ng-intelligent-plugin-layout', 5 | templateUrl: '../../../component/intelligent-plugin/layout/layout.component.html', 6 | styles: [ 7 | ] 8 | }) 9 | export class IntelligentPluginLayoutComponent extends EoIntelligentPluginLayoutComponent { 10 | } 11 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/intelligent-plugin/list/list.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | import { EoIntelligentPluginListComponent } from '../../../component/intelligent-plugin/list/list.component' 3 | 4 | @Component({ 5 | selector: 'eo-ng-intelligent-plugin-list', 6 | templateUrl: '../../../component/intelligent-plugin/list/list.component.html', 7 | styles: [ 8 | ] 9 | }) 10 | export class IntelligentPluginListComponent extends EoIntelligentPluginListComponent {} 11 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/intelligent-plugin/publish/publish.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | import { EoIntelligentPluginPublishComponent } from '../../../component/intelligent-plugin/publish/publish.component' 3 | 4 | @Component({ 5 | selector: 'eo-ng-intelligent-plugin-publish', 6 | templateUrl: '../../../component/intelligent-plugin/publish/publish.component.html', 7 | styles: [ 8 | ] 9 | }) 10 | export class IntelligentPluginPublishComponent extends EoIntelligentPluginPublishComponent {} 11 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/log-retrieval/conf.ts: -------------------------------------------------------------------------------- 1 | 2 | export const LogRetrievalTableHeadName = [ 3 | { 4 | title: '' 5 | }, 6 | { 7 | title: '' 8 | }, 9 | { 10 | title: '' 11 | }, { 12 | title: '', 13 | width: 98 14 | } 15 | ] 16 | 17 | export const LogRetrievalTableBody = [ 18 | { 19 | key: 'file', 20 | left: true, 21 | copy: true 22 | }, 23 | { 24 | key: 'size' 25 | }, 26 | { 27 | key: 'mod' 28 | }, 29 | { 30 | type: 'btn', 31 | right: true, 32 | btns: [{ 33 | title: '下载' 34 | }] 35 | } 36 | ] 37 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/log-retrieval/log-retrieval-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core' 2 | import { RouterModule, Routes } from '@angular/router' 3 | import { LogRetrievalComponent } from './log-retrieval.component' 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | component: LogRetrievalComponent 9 | } 10 | ] 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule] 15 | }) 16 | export class LogRetrievalRoutingModule { } 17 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/log-retrieval/type.ts: -------------------------------------------------------------------------------- 1 | 2 | export type LogFileData = { 3 | file:string 4 | size:string 5 | mod:string 6 | key:string 7 | } 8 | 9 | export type LogOutputData = { 10 | name:string 11 | tail:string 12 | files:Array 13 | active?:boolean // 折叠面板 14 | } 15 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/login/logo/logo.component.html: -------------------------------------------------------------------------------- 1 | EOLINK -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/login/logo/logo.component.scss: -------------------------------------------------------------------------------- 1 | eo-logo:host { 2 | img { 3 | width: 92px; 4 | } 5 | cursor: pointer; 6 | } 7 | 8 | ::selection { 9 | background: var(--find-password); 10 | } 11 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/login/logo/logo.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from '@angular/core' 2 | 3 | type LogoType = 'light' | 'dark' 4 | 5 | @Component({ 6 | selector: 'eo-ng-apinto-logo', 7 | templateUrl: './logo.component.html', 8 | styleUrls: ['./logo.component.scss'] 9 | }) 10 | export class LogoComponent { 11 | @Input() type: LogoType = 'light' 12 | } 13 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/login/password/password.component.scss: -------------------------------------------------------------------------------- 1 | form { 2 | width: 350px; 3 | padding: 28px 0 8px 0; 4 | } 5 | 6 | html { 7 | --antd-wave-shadow-color: var(--primary-color) !important; 8 | } 9 | 10 | .ant-input:hover { 11 | border-color: var(--primary-color); 12 | } 13 | 14 | .ant-input:focus, 15 | .ant-input-focused { 16 | border-color: var(--primary-color); 17 | box-shadow: 0 0 0 2px rgb(var(--primary-color), 20%); 18 | } 19 | 20 | button.ant-btn.ant-btn-primary, 21 | button.ant-btn.ant-btn-primary:hover, 22 | button.ant-btn.ant-btn-primary:focus { 23 | height: 40px; 24 | margin-top: 20px; 25 | } 26 | 27 | ::selection { 28 | background: var(--primary-color); 29 | } 30 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/not-found-page/not-found-page.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | import { Router } from '@angular/router' 3 | import { EoNgNavigationService } from '../../service/eo-ng-navigation.service' 4 | 5 | @Component({ 6 | selector: 'eo-ng-not-found-page', 7 | template: '', 8 | styles: [ 9 | ] 10 | }) 11 | export class NotFoundPageComponent { 12 | constructor (private router:Router, private navigation:EoNgNavigationService) { 13 | this.router.navigate([this.navigation.getPageRoute()]) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/plugin/plugin-management.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | import { Router } from '@angular/router' 3 | 4 | @Component({ 5 | selector: 'eo-ng-plugin-management', 6 | template: ` 7 | `, 8 | styles: [ 9 | ] 10 | }) 11 | export class PluginManagementComponent { 12 | constructor (private router:Router) { 13 | if (this.router.url.split('?')[0] === '/module-plugin') { 14 | this.router.navigate(['/', 'module-plugin', 'group', 'list']) 15 | } 16 | } 17 | 18 | ngDoCheck () { 19 | if (this.router.url.split('?')[0] === '/module-plugin') { 20 | this.router.navigate(['/', 'module-plugin', 'group', 'list']) 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/plugin/types/conf.ts: -------------------------------------------------------------------------------- 1 | import { THEAD_TYPE } from 'eo-ng-table' 2 | import { EO_TBODY_TYPE } from 'projects/eo-ng-apinto-table/src/public-api' 3 | 4 | export const PluginListStatusItems = [ 5 | { label: '全部', value: '' }, 6 | { label: '已启用', value: true }, 7 | { label: '未启用', value: false } 8 | ] 9 | 10 | export const PluginInstallConfigTableHeadName:THEAD_TYPE[] = [ 11 | { title: '参数名' }, 12 | { title: '参数值' }, 13 | { title: '描述' } 14 | ] 15 | 16 | export const PluginInstallConfigTableBody: EO_TBODY_TYPE[] = [ 17 | { 18 | key: 'name' 19 | }, 20 | { 21 | key: 'value', 22 | type: 'input', 23 | placeholderKey: 'placeholder' 24 | }, 25 | { key: 'desc' } 26 | ] 27 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/serv-governance/cache/cache.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | import { Router } from '@angular/router' 3 | 4 | @Component({ 5 | selector: 'eo-ng-cache', 6 | template: ` 7 | 8 | `, 9 | styles: [ 10 | ] 11 | }) 12 | export class CacheComponent { 13 | constructor (private router:Router) { 14 | if (this.router.url.split('?')[0] === '/serv-governance/cache') { 15 | this.router.navigate(['/', 'serv-governance', 'cache', 'group']) 16 | } 17 | } 18 | 19 | ngDoCheck () { 20 | if (this.router.url.split('?')[0] === '/serv-governance/cache') { 21 | this.router.navigate(['/', 'serv-governance', 'cache', 'group']) 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/serv-governance/filter/footer/footer.component.html: -------------------------------------------------------------------------------- 1 | 10 | 13 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/serv-governance/fuse/fuse.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | import { Router } from '@angular/router' 3 | 4 | @Component({ 5 | selector: 'eo-ng-fuse', 6 | template: ` 7 | 8 | `, 9 | styles: [ 10 | ] 11 | }) 12 | export class FuseComponent { 13 | constructor (private router:Router) { 14 | if (this.router.url === '/serv-governance/fuse') { 15 | this.router.navigate(['/', 'serv-governance', 'fuse', 'group']) 16 | } 17 | } 18 | 19 | ngDoCheck () { 20 | if (this.router.url === '/serv-governance/fuse') { 21 | this.router.navigate(['/', 'serv-governance', 'fuse', 'group']) 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/serv-governance/grey/grey.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | import { Router } from '@angular/router' 3 | 4 | @Component({ 5 | selector: 'eo-ng-grey', 6 | template: ` 7 | 8 | `, 9 | styles: [ 10 | ] 11 | }) 12 | export class GreyComponent { 13 | constructor (private router:Router) { 14 | if (this.router.url === '/serv-governance/grey') { 15 | this.router.navigate(['/', 'serv-governance', 'grey', 'group']) 16 | } 17 | } 18 | 19 | ngDoCheck () { 20 | if (this.router.url === '/serv-governance/grey') { 21 | this.router.navigate(['/', 'serv-governance', 'grey', 'group']) 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/serv-governance/traffic/message/message.component.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/serv-governance/traffic/traffic.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | import { Router } from '@angular/router' 3 | 4 | @Component({ 5 | selector: 'eo-ng-traffic', 6 | template: ` 7 | 8 | `, 9 | styles: [ 10 | ] 11 | }) 12 | export class TrafficComponent { 13 | constructor (private router:Router) { 14 | if (this.router.url === '/serv-governance/traffic') { 15 | this.router.navigate(['/', 'serv-governance', 'traffic', 'group']) 16 | } 17 | } 18 | 19 | ngDoCheck () { 20 | if (this.router.url === '/serv-governance/traffic') { 21 | this.router.navigate(['/', 'serv-governance', 'traffic', 'group']) 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/serv-governance/visit/visit.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | import { Router } from '@angular/router' 3 | 4 | @Component({ 5 | selector: 'eo-ng-visit', 6 | template: ` 7 | 8 | `, 9 | styles: [ 10 | ] 11 | }) 12 | export class VisitComponent { 13 | constructor (private router:Router) { 14 | if (this.router.url === '/serv-governance/visit') { 15 | this.router.navigate(['/', 'serv-governance', 'visit', 'group']) 16 | } 17 | } 18 | 19 | ngDoCheck () { 20 | if (this.router.url === '/serv-governance/visit') { 21 | this.router.navigate(['/', 'serv-governance', 'visit', 'group']) 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/system/email/system-email.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | 3 | @Component({ 4 | selector: 'eo-ng-system-email', 5 | template: ` 6 | `, 7 | styles: [ 8 | ] 9 | }) 10 | export class SystemEmailComponent { 11 | } 12 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/system/external-app/external-app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | 3 | @Component({ 4 | selector: 'eo-ng-external-app', 5 | template: ` 6 | `, 7 | styles: [ 8 | ] 9 | }) 10 | export class ExternalAppComponent { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/system/system.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | 3 | @Component({ 4 | selector: 'eo-ng-system', 5 | template: ` 6 | `, 7 | styles: [ 8 | ` 9 | :host ::ng-deep{ 10 | td { 11 | eo-ng-select.ant-select, 12 | eo-ng-select-top-control.ant-select-selector { 13 | width: 100% !important; 14 | } 15 | } 16 | }` 17 | ] 18 | }) 19 | export class SystemComponent { 20 | } 21 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/layout/system/webhook/webhook.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | 3 | @Component({ 4 | selector: 'eo-ng-system-webhook', 5 | template: ` 6 | 7 | `, 8 | styles: [ 9 | ] 10 | }) 11 | export class SystemWebhookComponent { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/pipe/change-word-color.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core' 2 | 3 | @Pipe({ 4 | name: 'changeWordColor' 5 | }) 6 | export class ChangeWordColorPipe implements PipeTransform { 7 | // value:需转换的字符串,args[0]:需改变颜色的字符串,args[1]:改变后的颜色 8 | transform (value: string, ...args:Array): unknown { 9 | const wordArray:Array = value.split(args[0]) 10 | return wordArray.join(`${args[0]}`) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/service/crypto.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core' 2 | import * as CryptoJS from 'crypto-js' 3 | 4 | @Injectable({ 5 | providedIn: 'root' 6 | }) 7 | export class CryptoService { 8 | private key:string = '1e42=7838a1vfc6n' 9 | 10 | // AES加密,登录、修改密码用, 向量默认 1e42=7838a1vfc6n, inputKey是用户名,inputData是密码 11 | encryptByEnAES (inputKey:string, inputData:string, inputIv?:string):string { 12 | const tmpIv = CryptoJS.enc.Latin1.parse(inputIv || this.key) 13 | const tmpKey = CryptoJS.enc.Latin1.parse(CryptoJS.MD5(inputKey).toString() || '') 14 | return CryptoJS.enc.Base64.stringify(CryptoJS.AES.encrypt(inputData, tmpKey, { 15 | iv: tmpIv, 16 | mode: CryptoJS.mode.CBC, 17 | padding: CryptoJS.pad.Pkcs7 18 | }).ciphertext) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /frontend/projects/core/src/app/service/http-interceptors/index.ts: -------------------------------------------------------------------------------- 1 | import { HTTP_INTERCEPTORS } from '@angular/common/http' 2 | import { ErrorInterceptor } from './error.interceptor' 3 | 4 | /** Http interceptor providers in outside-in order */ 5 | export const httpInterceptorProviders = [ 6 | { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true } 7 | ] 8 | -------------------------------------------------------------------------------- /frontend/projects/core/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/frontend/projects/core/src/assets/.gitkeep -------------------------------------------------------------------------------- /frontend/projects/core/src/assets/default-guide-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/frontend/projects/core/src/assets/default-guide-icon.png -------------------------------------------------------------------------------- /frontend/projects/core/src/assets/default-navigation-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/frontend/projects/core/src/assets/default-navigation-icon.png -------------------------------------------------------------------------------- /frontend/projects/core/src/assets/default-plugin-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /frontend/projects/core/src/assets/favicon-pro.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/frontend/projects/core/src/assets/favicon-pro.ico -------------------------------------------------------------------------------- /frontend/projects/core/src/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/frontend/projects/core/src/assets/favicon.ico -------------------------------------------------------------------------------- /frontend/projects/core/src/assets/guide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/frontend/projects/core/src/assets/guide.jpg -------------------------------------------------------------------------------- /frontend/projects/core/src/assets/logo/logo_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/frontend/projects/core/src/assets/logo/logo_dark.png -------------------------------------------------------------------------------- /frontend/projects/core/src/assets/logo/logo_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/frontend/projects/core/src/assets/logo/logo_light.png -------------------------------------------------------------------------------- /frontend/projects/core/src/assets/side_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/frontend/projects/core/src/assets/side_bg.jpg -------------------------------------------------------------------------------- /frontend/projects/core/src/assets/theme/dark.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors": { 3 | "primary": "#7371fc", 4 | "text": "rgba(243, 243, 243, 0.9)", 5 | "inputIcon": "#fff", 6 | "textSecondary": "#ccc", 7 | "border": "rgba(255, 255, 255, 0.1)", 8 | "background": "#212121", 9 | "barBackground": "#212121", 10 | "disabledText": "#666", 11 | "disabledBackground": "#282828", 12 | "textLink": "#1890ff", 13 | "textLinkHover": "#40a9ff", 14 | "textLinkActive": "#096dd9", 15 | "divider": "rgba(255, 255, 255, 0.1)", 16 | "alertDefaultBackground": "rgba(149,149,149,.1)", 17 | "scrollbarTrackBackground": "#212121", 18 | "scrollbarThumbBackground": "rgba(255, 255, 255, 0.2)", 19 | "popoverBackground": "#fff", 20 | "popoverText": "#333", 21 | "tableRowHoverBackground": "#555555" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /frontend/projects/core/src/assets/theme/light.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors": { 3 | "primary": "#7371fc", 4 | "text": "#333", 5 | "textSecondary": "#999", 6 | "inputIcon": "rgba(0, 0, 0, 0.25)", 7 | "border": "rgba(0, 0, 0, 0.07)", 8 | "background": "#fff", 9 | "barBackground": "#fafafa", 10 | "disabledText": "#bbbbbb", 11 | "disabledBackground": "#f6f6f6", 12 | "textLink": "#1890ff", 13 | "textLinkHover": "#40a9ff", 14 | "textLinkActive": "#096dd9", 15 | "divider": "rgba(0,0,0,.06)", 16 | "alertDefaultBackground": "rgba(149,149,149,.1)", 17 | "scrollbarTrackBackground": "rgba(255, 255, 255, 0.05)", 18 | "scrollbarThumbBackground": "rgba(0, 0, 0, 0.2)", 19 | "popoverText": "#fff", 20 | "popoverBackground": "rgba(0,0,0,.75)", 21 | "layoutSidebarText": "#333" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /frontend/projects/core/src/environments/basic.ts: -------------------------------------------------------------------------------- 1 | export const defaultEnvironment = { 2 | } 3 | -------------------------------------------------------------------------------- /frontend/projects/core/src/environments/environment.business.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | urlPrefix: '/', 4 | isBusiness: true 5 | } 6 | -------------------------------------------------------------------------------- /frontend/projects/core/src/environments/environment.business.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: false, 3 | isBusiness: true, 4 | urlPrefix: 5 | '/' 6 | // 'https://mockapi.eolink.com/K25EPjsf31dac8880a551fe2672247d21218bf854cbcf60/' 7 | // 'http://uat.apikit.com:11204/mockApi/Pn83XY3f27fddad8ba775d3bec6b2b0998168ad3db5ccbb/' 8 | } 9 | -------------------------------------------------------------------------------- /frontend/projects/core/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | urlPrefix: '/', 4 | isBusiness: false 5 | } 6 | -------------------------------------------------------------------------------- /frontend/projects/core/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: false, 3 | isBusiness: false, 4 | urlPrefix: 5 | '/' 6 | // 'https://mockapi.eolink.com/K25EPjsf31dac8880a551fe2672247d21218bf854cbcf60/' 7 | // 'http://uat.apikit.com:11204/mockApi/Pn83XY3f27fddad8ba775d3bec6b2b0998168ad3db5ccbb/' 8 | } 9 | 10 | /* 11 | * For easier debugging in development mode, you can import the following file 12 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 13 | * 14 | * This import should be commented out in production mode because it will have a negative impact 15 | * on performance if an error is thrown. 16 | */ 17 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 18 | -------------------------------------------------------------------------------- /frontend/projects/core/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/frontend/projects/core/src/favicon.ico -------------------------------------------------------------------------------- /frontend/projects/core/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Apinto 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /frontend/projects/core/src/input.style.scss: -------------------------------------------------------------------------------- 1 | input[type='file'] { 2 | display: none !important; 3 | } 4 | 5 | textarea.ant-input { 6 | min-height: 68px; 7 | height: 68px; 8 | } 9 | 10 | input[type='number']::-webkit-inner-spin-button, 11 | input[type='number']::-webkit-outer-spin-button { 12 | -webkit-appearance: none; 13 | margin: 0; 14 | } 15 | input[type='number'] { 16 | -moz-appearance: textfield; 17 | } 18 | -------------------------------------------------------------------------------- /frontend/projects/core/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core' 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' 3 | 4 | import { AppModule } from './app/app.module' 5 | import { environment } from './environments/environment' 6 | 7 | if (environment.production) { 8 | enableProdMode() 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.error(err)) 13 | -------------------------------------------------------------------------------- /frontend/projects/core/src/select.style.scss: -------------------------------------------------------------------------------- 1 | // 表格自带分页的选择器宽度 2 | .ant-pagination-options { 3 | .ant-select, 4 | nz-select-top-control.ant-select-selector { 5 | width: auto !important; 6 | } 7 | } 8 | // select光标与placeholder位置,待组件库修改 9 | .ant-select-multiple .ant-select-selection-search { 10 | margin-inline-start: 2px; 11 | } 12 | 13 | eo-ng-select:not(.ant-select-open) 14 | eo-ng-select-top-control 15 | nz-select-search.ant-select-selection-search { 16 | width: 1px !important; 17 | } 18 | 19 | .ant-select-item { 20 | label[eo-ng-checkbox] { 21 | padding-top: 0px; 22 | } 23 | } 24 | 25 | .ant-select-selection-placeholder { 26 | color: var(--input-placeholder-color) !important; 27 | } 28 | -------------------------------------------------------------------------------- /frontend/projects/core/src/variables.css: -------------------------------------------------------------------------------- 1 | /* UI component */ 2 | :root { 3 | --icon-size: 14px; 4 | --border-radius: 4px; 5 | 6 | --layout-header-height: 50px; 7 | --layout-footer-height: 30px; 8 | 9 | --btn-icon-margin: 5px; 10 | --button-height: 32px; 11 | --tabs-height: 43px; 12 | --tree-item-height: 30px; 13 | --collapse-header-height: 46px; 14 | 15 | --table-font-size: 14px; 16 | --table-row-height: 40px; 17 | --table-item-padding: 4px; 18 | 19 | --padding-x: 20px; 20 | --padding-y: 15px; 21 | --padding: var(--padding-y) var(--padding-x); 22 | --margin: 20px; 23 | } 24 | /* System customer */ 25 | :root { 26 | --layout-sidebar-width: 90px; 27 | --layout-sidebar-item-height: auto; 28 | --edit-inside-bar-height: 53px; 29 | } 30 | -------------------------------------------------------------------------------- /frontend/projects/eo-ng-apinto-table/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/eo-ng-apinto-table", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } -------------------------------------------------------------------------------- /frontend/projects/eo-ng-apinto-table/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eo-ng-apinto-table", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^14.0.0", 6 | "@angular/core": "^14.0.0" 7 | }, 8 | "dependencies": { 9 | "tslib": "^2.3.0" 10 | } 11 | } -------------------------------------------------------------------------------- /frontend/projects/eo-ng-apinto-table/src/lib/types.ts: -------------------------------------------------------------------------------- 1 | import { TemplateRef } from '@angular/core' 2 | import { TBODY_TYPE, THEAD_TYPE } from 'eo-ng-table' 3 | 4 | export interface EO_TBODY_TYPE extends TBODY_TYPE{ 5 | check?:Function 6 | tooltip?:string | TemplateRef 7 | json?:boolean 8 | copy?:boolean 9 | } 10 | 11 | export interface EO_THEAD_TYPE extends THEAD_TYPE{ 12 | required?:boolean 13 | titleString?:string // require用 14 | tooltip?:string 15 | } 16 | -------------------------------------------------------------------------------- /frontend/projects/eo-ng-apinto-table/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of eo-ng-apinto-table 3 | */ 4 | 5 | export * from './lib/eo-ng-apinto-table.module' 6 | export * from './lib/table/table.component' 7 | export * from './lib/types' 8 | -------------------------------------------------------------------------------- /frontend/projects/eo-ng-apinto-table/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "outDir": "../../dist/eo-ng-apinto-table/tsc-bundle", 5 | "module": "umd", 6 | "moduleResolution": "node", 7 | "sourceMap": true, 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "lib": ["es2015", "dom"], 11 | "noImplicitAny": true, 12 | "suppressImplicitAnyIndexErrors": true, 13 | "skipLibCheck": true, 14 | "allowSyntheticDefaultImports": true 15 | }, 16 | "exclude": [ 17 | "./**/*.test.ts", 18 | "./**/test.ts", 19 | "./**/*.spec.ts", 20 | "./**/*.test.js", 21 | "./**/*.spec.js" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /frontend/projects/eo-ng-apinto-table/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "../../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "../../out-tsc/lib", 6 | "declaration": true, 7 | "declarationMap": true, 8 | "inlineSources": true, 9 | "types": [] 10 | }, 11 | "exclude": [ 12 | "src/test.ts", 13 | "**/*.spec.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /frontend/projects/eo-ng-apinto-table/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.lib.json", 4 | "compilerOptions": { 5 | "declarationMap": false 6 | }, 7 | "angularCompilerOptions": { 8 | "compilationMode": "partial" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /frontend/projects/eo-ng-apinto-table/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "../../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "../../out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /frontend/proxy.config.demo.json: -------------------------------------------------------------------------------- 1 | { 2 | "/api": { 3 | "target": "https://demo-dashboard.apinto.com/", 4 | "changeOrigin": true 5 | }, 6 | "/_system": { 7 | "target": "https://demo-dashboard.apinto.com/", 8 | "changeOrigin": true 9 | }, 10 | "/sso": { 11 | "target": "https://demo-dashboard.apinto.com/", 12 | "changeOrigin": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /frontend/test/setup-jest.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular/setup-jest' 2 | -------------------------------------------------------------------------------- /frontend/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": ["node"] 7 | }, 8 | "files": [ 9 | "projects/core/src/main.ts", 10 | "projects/core/src/polyfills.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /frontend/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true, 4 | "outDir": "./out-tsc/spec", 5 | "types": ["jest", "node"], 6 | "target": "es6", 7 | "module": "umd", 8 | "moduleResolution": "node", 9 | "sourceMap": true, 10 | "emitDecoratorMetadata": true, 11 | "experimentalDecorators": true, 12 | "lib": ["es2015", "es2016", "es2019", "dom"], 13 | "noImplicitAny": true, 14 | "suppressImplicitAnyIndexErrors": true, 15 | "skipLibCheck": true, 16 | "allowSyntheticDefaultImports": true, 17 | "baseUrl": "./" 18 | }, 19 | "include": ["src/**/*.spec.ts", "src/**/*.d.ts"] 20 | } 21 | -------------------------------------------------------------------------------- /grpc-service/notice_send.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/eolinker/apinto-monitor/grpc-service"; 4 | 5 | message NoticeSendResp { 6 | int32 send_status = 1; 7 | string err_msg = 2; 8 | } 9 | 10 | message NoticeMsg { 11 | string title = 1; 12 | string msg = 2; 13 | } 14 | 15 | message NoticeSendReq { 16 | repeated string user_names = 1; 17 | int32 namespace_id = 2; 18 | map notices = 3; 19 | } 20 | 21 | service NoticeSend { 22 | rpc Send(NoticeSendReq) returns (NoticeSendResp) {} 23 | } 24 | -------------------------------------------------------------------------------- /initialize/inner-plugin-manager/embed_plugin.go: -------------------------------------------------------------------------------- 1 | package inner_plugin_manager 2 | 3 | var _ IInnerPlugin = (*embedPlugin)(nil) 4 | 5 | type embedPlugin struct { 6 | //TODO 存FS? 7 | } 8 | 9 | func (e embedPlugin) GetDefine() interface{} { 10 | //TODO implement me 11 | panic("implement me") 12 | } 13 | 14 | func (e embedPlugin) GetIcon(fileName string) ([]byte, error) { 15 | //TODO implement me 16 | panic("implement me") 17 | } 18 | 19 | func (e embedPlugin) GetReadme(fileName string) ([]byte, error) { 20 | //TODO implement me 21 | panic("implement me") 22 | } 23 | 24 | func (e embedPlugin) GetResourcesFile(filePath string) ([]byte, error) { 25 | //TODO implement me 26 | panic("implement me") 27 | } 28 | -------------------------------------------------------------------------------- /initialize/inner-plugin-manager/export.go: -------------------------------------------------------------------------------- 1 | package inner_plugin_manager 2 | 3 | import "embed" 4 | 5 | // RegisterInnerPluginFromEmbed 保存来源为内嵌目录的内置插件 6 | func RegisterInnerPluginFromEmbed(pluginID string, source embed.FS) error { 7 | //TODO 从来源解析出实现了IInnerPlugin的资源 8 | 9 | _innerPluginManager.setInnerPlugin(pluginID, &embedPlugin{}) 10 | return nil 11 | } 12 | 13 | func EnablePlugin(pluginID string) error { 14 | return _innerPluginManager.enableInnerPlugin(pluginID) 15 | } 16 | 17 | func GetInnerPlugin(pluginID string) (IInnerPlugin, bool) { 18 | return _innerPluginManager.getInnerPlugin(pluginID) 19 | } 20 | -------------------------------------------------------------------------------- /initialize/inner-plugin-manager/interface.go: -------------------------------------------------------------------------------- 1 | package inner_plugin_manager 2 | 3 | type IInnerPlugin interface { 4 | GetDefine() interface{} 5 | GetIcon(fileName string) ([]byte, error) 6 | GetReadme(fileName string) ([]byte, error) 7 | GetResourcesFile(filePath string) ([]byte, error) 8 | } 9 | -------------------------------------------------------------------------------- /initialize/plugin-group/plugin_group.yml: -------------------------------------------------------------------------------- 1 | - id: "core_module" 2 | name: "核心模块" 3 | - id: "strategy" 4 | name: "策略" 5 | - id: "access_auth" 6 | name: "访问鉴权" 7 | - id: "security" 8 | name: "安全" 9 | - id: "data" 10 | name: "数据处理" 11 | - id: "log" 12 | name: "日志" 13 | - id: "devops" 14 | name: "DevOps" 15 | -------------------------------------------------------------------------------- /initialize/plugin_group.go: -------------------------------------------------------------------------------- 1 | package initialize 2 | 3 | import ( 4 | _ "embed" 5 | 6 | "gopkg.in/yaml.v3" 7 | ) 8 | 9 | var ( 10 | //go:embed plugin_group.yml 11 | pluginGroupsContent []byte 12 | 13 | groupList []*PluginGroupsItem 14 | ) 15 | 16 | type PluginGroupsItem struct { 17 | ID string `json:"id" yaml:"id"` 18 | Name string `json:"name" yaml:"name"` 19 | } 20 | 21 | func init() { 22 | // 初始化插件分组列表 23 | groupList = make([]*PluginGroupsItem, 0) 24 | err := yaml.Unmarshal(pluginGroupsContent, &groupList) 25 | if err != nil { 26 | panic(err) 27 | } 28 | } 29 | 30 | func GetModulePluginGroups() []*PluginGroupsItem { 31 | return groupList 32 | } 33 | -------------------------------------------------------------------------------- /initialize/plugin_group.yml: -------------------------------------------------------------------------------- 1 | - id: "core_module" 2 | name: "核心模块" 3 | - id: "strategy" 4 | name: "策略" 5 | - id: "access_auth" 6 | name: "访问鉴权" 7 | - id: "security" 8 | name: "安全" 9 | - id: "log" 10 | name: "日志" 11 | - id: "devops" 12 | name: "DevOps" -------------------------------------------------------------------------------- /initialize/plugins/embed/api.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | 管理和配置API转发信息,支持配置多协议接口,包括HTTP/HTTPS、Webservice、Restful、SOAP等多种请求协议,支持从Apikit、Postcat、Swagger等API管理工具中一键同步API。 3 | ## 功能特性 4 | - 管理和配置API转发信息,包括:API请求路径、上游服务、请求协议、请求方法、超时时间、重试次数等。 5 | - 一键同步Apikit、Postcat、Swagger等API管理工具中的API。 6 | - 一键发布API到集群节点,供客户端调用。 7 | - 支持HTTP/HTTPS、Webservice、Restful、SOAP等多种请求协议。 8 | 9 | ## 更新日志 10 | ### V1.0(2023-4-30) 11 | - 插件上线 -------------------------------------------------------------------------------- /initialize/plugins/embed/api.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/api.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/api.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "api.apinto.com" 2 | name: "api" 3 | cname: "API管理" 4 | resume: "管理和配置API转发信息,支持配置多协议接口,包括HTTP/HTTPS、Webservice、Restful、SOAP等多种请求协议。" 5 | version: "v1.0.7" 6 | icon: "logo.png" 7 | driver: "api.apinto.com" 8 | type: 1 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: false 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: true 14 | front: router 15 | navigation: "navigation.api" 16 | group_id: "core_module" -------------------------------------------------------------------------------- /initialize/plugins/embed/apispace.apinto.com/apispace.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/apispace.apinto.com/apispace.jpg -------------------------------------------------------------------------------- /initialize/plugins/embed/apispace.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "apispace.apinto.com" 2 | name: "apispace" 3 | cname: "APISpace接口商店" 4 | resume: "APISpace是Eolink旗下专业的API开放与交易平台,为超过100万开发者提供专业的API服务,所有 API均提供免费试用,让您无忧探索广阔的API世界" 5 | version: "v1.0.1" 6 | icon: "apispace.jpg" 7 | driver: "remote" 8 | type: 2 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: true 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: true 14 | front: 15 | navigation: "navigation.api_market" 16 | group_id: "" 17 | define: 18 | internet: true 19 | server: "https://www.apispace.com" 20 | path: "/explore/service/?utm_source=apinto" -------------------------------------------------------------------------------- /initialize/plugins/embed/application.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | 应用是对请求来源的抽象概念,其可以是一个客户端App,也可以是一个后端服务,还可以是Web App...... 3 | 4 | 应用管理统一管理应用在各个集群的生命周期。应用作为业务通讯的发起者,贯穿整个调用链。 5 | 6 | 在安全方面,网关可以对应用请求的流量进行鉴权认证和授权访问,保障请求流量安全合规转发到后端服务。 7 | 8 | 在监控方面,网关可以在应用维度监控调用API情况,帮助运维或运营分析应用调用趋势,继而做出相应的策略。 9 | 10 | ## 功能特性 11 | - 支持多种鉴权方式 12 | - 单应用多用户模式 13 | - 支持以应用为单位参与服务治理 14 | 15 | ## 更新日志 16 | ### V1.0(2023-4-30) 17 | - 插件上线 -------------------------------------------------------------------------------- /initialize/plugins/embed/application.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/application.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/application.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "application.apinto.com" 2 | name: "app" 3 | cname: "应用管理" 4 | resume: "应用管理统一管理应用在各个集群的生命周期。应用作为业务通讯的发起者,贯穿整个调用链。" 5 | version: "v1.0.7" 6 | icon: "logo.png" 7 | driver: "application.apinto.com" 8 | type: 1 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: false 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: true 14 | front: 15 | navigation: "navigation.application" 16 | group_id: "core_module" -------------------------------------------------------------------------------- /initialize/plugins/embed/audit.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | Debug日志记录使用者在控制台操作的事件,包括创建、编辑、删除、上线、下线等。 3 | 4 | 通过Debug日志,我们可以将操作记录作为证据留痕。当系统存在多个用户操作时,一定会出现纠纷,特别是基于系统开展运营时,用户数据出现操作问题,到底是谁的责任? 5 | 6 | 在错误面前,鲜有人主动承认,此时,日志就有了用武之地,定位到人后,除定责外,还能起到对系统坚定信心的作用。 7 | ## 功能特性 8 | - 提供详细的控制台操作日志信息 9 | - 支持多条件筛选日志,包括操作类型、操作对象、操作时间 10 | - 支持关键字查询用户操作日志信息 11 | ## 更新日志 12 | ### V1.0(2023-4-30) 13 | - 插件上线 -------------------------------------------------------------------------------- /initialize/plugins/embed/audit.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/audit.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/audit.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "audit.apinto.com" 2 | name: "audit-log" 3 | cname: "Debug日志" 4 | resume: "Debug日志记录使用者在控制台操作的事件,包括创建、编辑、删除、上线、下线等。" 5 | version: "v1.0.7" 6 | icon: "logo.png" 7 | driver: "audit.apinto.com" 8 | type: 2 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: true 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: true 14 | front: 15 | navigation: "navigation.system" 16 | group_id: "log" -------------------------------------------------------------------------------- /initialize/plugins/embed/cluster.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | 管理和维护多业务、多环境集群,帮助管理同城双活、两地三中心、异地多活等架构场景集群配置,保证集群间信息同步。支持以集群为最小粒度发布服务、上游信息、策略、插件配置、环境变量等相关信息。 3 | ## 功能特性 4 | - 支持同城双活、两地三中心、异地多活架构集群场景配置同步。 5 | - 支持多业务、多环境集群同步。 6 | - 支持以集群为最小粒度发布、下线配置信息。 7 | 8 | ## 更新日志 9 | ### V1.0(2023-4-30) 10 | - 插件上线 -------------------------------------------------------------------------------- /initialize/plugins/embed/cluster.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/cluster.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/cluster.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "cluster.apinto.com" 2 | name: "cluster" 3 | cname: "集群" 4 | resume: "管理和维护多业务、多环境集群,帮助管理同城双活、两地三中心、异地多活等架构场景集群配置,保证集群间信息同步。" 5 | version: "v1.0.7" 6 | icon: "logo.png" 7 | driver: "cluster.apinto.com" 8 | type: 1 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: false 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: true 14 | front: deploy 15 | navigation: "navigation.infrastructure" 16 | group_id: "core_module" -------------------------------------------------------------------------------- /initialize/plugins/embed/discovery.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | 服务发现是指使用一个注册中心来记录分布式系统中的全部服务的信息,以便其他服务能够快速的找到这些已注册的服务。 3 | 4 | 服务发现有三个角色,服务提供者、服务消费者和服务中介。 5 | - 服务中介:联系服务提供者和服务消费者的桥梁。 6 | - 服务提供者:将自己提供的服务地址注册到服务中介。 7 | - 服务消费者:从服务中介那里查找自己想要的服务的地址,然后享受这个服务。服务中介提供多个服务,每个服务对应多个服务提供者。 8 | 9 | 当服务提供者的节点发生宕机、离线等原因导致不可正常提供服务时,服务中介会及时获取相关信息,将相关节点信息从记录表中删除,服务消费者将不再请求故障节点。 10 | 11 | 当服务提供者新辑入时,及时通知服务中介,此时,服务消费者就可以从众多节点中选择其一进行消费。 12 | ## 功能特性 13 | - 支持接入Eureka、Consul、Nacos 14 | - 静态服务发现支持健康检查,实时监测节点的连通情况 15 | - 支持引用环境变量 16 | ## 更新日志 17 | ### V1.0(2023-4-30) 18 | - 插件上线 -------------------------------------------------------------------------------- /initialize/plugins/embed/discovery.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/discovery.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/email.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | 配置系统邮件服务器信息,系统内邮件(如告警邮件)将会使用该邮件服务器发送。 3 | ## 功能特性 4 | - 使用SMTP协议发送邮件 5 | - 支持SSL/TLS协议 6 | ## 更新日志 7 | ### V1.0(2023-4-30) 8 | - 插件上线 -------------------------------------------------------------------------------- /initialize/plugins/embed/email.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/email.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/email.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "email.apinto.com" 2 | name: "email" 3 | cname: "邮箱设置" 4 | resume: "配置系统邮件服务器信息,系统内邮件(如告警邮件)将会使用该邮件服务器发送。" 5 | version: "v1.0.7" 6 | icon: "logo.png" 7 | driver: "email.apinto.com" 8 | type: 2 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: true 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: true 14 | front: system 15 | navigation: "navigation.system" 16 | group_id: "" -------------------------------------------------------------------------------- /initialize/plugins/embed/ext_app.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | OpenAPI 定义 Web API 的标准接口描述和编程语言无关接口描述。 它使人类和计算机可以发现和了解服务的功能,而无需访问源代码、其他文档或检查网络流量。 3 | 4 | 利用该插件的提供的OpenAPI,将内容进行重新搭配,从而制作出独特的、具有新价值的新应用/产品。 5 | 6 | API管理平台Apikit、Postcat已经接入了OpenAPI,只需简单几步配置,从能将Apikit、Postcat中的API信息一键导入到Apinto网关。 7 | ## 功能特性 8 | - 提供OpenAPI供第三方应用/产品集成。 9 | - 配置外部应用,一键同步Apikit、Postcat的API信息到Apinto网关。 10 | 11 | ## 更新日志 12 | ### V1.0(2023-4-30) 13 | - 插件上线 -------------------------------------------------------------------------------- /initialize/plugins/embed/ext_app.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/ext_app.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/ext_app.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "ext_app.apinto.com" 2 | name: "ext-app" 3 | cname: "OpenAPI" 4 | resume: "利用该插件的提供的OpenAPI,将内容进行重新搭配,从而制作出独特的、具有新价值的新应用/产品。" 5 | version: "v1.0.1" 6 | icon: "logo.png" 7 | driver: "ext_app.apinto.com" 8 | type: 2 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: true 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: true 14 | front: system 15 | navigation: "navigation.system" 16 | group_id: "devops" -------------------------------------------------------------------------------- /initialize/plugins/embed/log.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | 日志检索提供基本的针对apinto节点的日志检索能力 3 | ## 功能特性 4 | - 针对节点,查询所有文件类型的日志列表 5 | - 支持追踪节点日志、请求Access日志 6 | - 支持在控制台下载日志,无需进入服务器操作 7 | - 按日志对象监视新增日志 8 | ## 功能截图 9 | ### 日志列表 10 | 11 | ![](http://data.eolinker.com/course/EDkWnjwd0a30690d772fbbcb73d5c2234a1df64e720bebc.png) 12 | 13 | ### 追踪日志 14 | 15 | ![](http://data.eolinker.com/course/rxHq6RY9912efadbbc10437cbe58dad65bb6c7f71389d70.png) 16 | 17 | ## 版本需求 18 | 需要 apinto版本 0.13 及以上 19 | ## 更新日志 20 | ### V1.0(2023-6-19) 21 | - 插件上线 -------------------------------------------------------------------------------- /initialize/plugins/embed/log.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "log.apinto.com" 2 | name: "log" 3 | cname: "日志检索" 4 | resume: "检索apinto的文件日志,包括节点日志和基于文件驱动的access日志" 5 | version: "v1.0.3" 6 | icon: "日志检索.png" 7 | driver: "log.apinto.com" 8 | type: 2 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: true 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: true 14 | front: 15 | navigation: "navigation.system" 16 | group_id: "log" -------------------------------------------------------------------------------- /initialize/plugins/embed/log.apinto.com/日志检索.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/log.apinto.com/日志检索.png -------------------------------------------------------------------------------- /initialize/plugins/embed/module_plugin.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | # 企业插件 -------------------------------------------------------------------------------- /initialize/plugins/embed/module_plugin.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/module_plugin.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/module_plugin.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "module_plugin.apinto.com" 2 | name: "module-plugin" 3 | cname: "插件管理" 4 | resume: "" 5 | version: "v1.0.5" 6 | icon: "logo.png" 7 | driver: "module_plugin.apinto.com" 8 | type: 0 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: false 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: false 14 | front: 15 | navigation: "navigation.module_plugin" 16 | group_id: "core_module" -------------------------------------------------------------------------------- /initialize/plugins/embed/open_api.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | OpenAPI 定义 Web API 的标准接口描述和编程语言无关接口描述。 它使人类和计算机可以发现和了解服务的功能,而无需访问源代码、其他文档或检查网络流量。 3 | 4 | 利用该插件的提供的OpenAPI,将内容进行重新搭配,从而制作出独特的、具有新价值的新应用/产品。 5 | 6 | API管理平台Apikit、Postcat已经接入了OpenAPI,只需简单几步配置,从能将Apikit、Postcat中的API信息一键导入到Apinto网关。 7 | ## 功能特性 8 | - 提供OpenAPI供第三方应用/产品集成。 9 | - 配置外部应用,一键同步Apikit、Postcat的API信息到Apinto网关。 10 | 11 | ## 更新日志 12 | ### V1.0(2023-4-30) 13 | - 插件上线 -------------------------------------------------------------------------------- /initialize/plugins/embed/open_api.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/open_api.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/open_api.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "open_api.apinto.com" 2 | name: "open_api" 3 | cname: "open-api" 4 | resume: "利用该插件的提供的OpenAPI,将内容进行重新搭配,从而制作出独特的、具有新价值的新应用/产品。" 5 | version: "v1.0.7" 6 | icon: "logo.png" 7 | driver: "open_api.apinto.com" 8 | type: 0 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: false 11 | is_can_uninstall: false 12 | visible_in_navigation: false 13 | visible_in_market: false 14 | front: "" 15 | group_id: "core_module" -------------------------------------------------------------------------------- /initialize/plugins/embed/plugin.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | # 全局插件 -------------------------------------------------------------------------------- /initialize/plugins/embed/plugin.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/plugin.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/plugin.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "plugin.apinto.com" 2 | name: "plugin" 3 | cname: "节点插件" 4 | resume: "" 5 | version: "v1.0.3" 6 | icon: "logo.png" 7 | driver: "plugin.apinto.com" 8 | type: 0 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: false 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: false 14 | front: deploy 15 | navigation: "navigation.infrastructure" 16 | group_id: "core_module" -------------------------------------------------------------------------------- /initialize/plugins/embed/plugin_template.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | # 插件模板 -------------------------------------------------------------------------------- /initialize/plugins/embed/plugin_template.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/plugin_template.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/plugin_template.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "plugin_template.apinto.com" 2 | name: "plugin-template" 3 | cname: "API操作模板" 4 | resume: "" 5 | version: "v1.0.4" 6 | icon: "logo.png" 7 | driver: "plugin_template.apinto.com" 8 | type: 0 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: false 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: false 14 | front: router 15 | navigation: "navigation.public_config" 16 | group_id: "core_module" -------------------------------------------------------------------------------- /initialize/plugins/embed/strategy-cache.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | 缓存是一种本地保存远端资源的机制,不管是在客户端、还是在服务端存储着,用相同的URL进行数据请求,可以直接从缓存中请求资源而不再访问源服务器。 3 | 4 | 数据缓存大致可以分为:数据库缓存、服务器端缓存(代理服务器缓存、CDN缓存)、浏览器缓存。 5 | 6 | 其意义主要在: 7 | - 避免了冗余的数据传输,节省流量; 8 | - 加快了用户访问网页的速度; 9 | - 减小了服务器的压力。 10 | 11 | Apinto网关数据缓存本质属于代理服务器缓存,通过缓存上游服务的静态资源,如:图片、静态页面等资源,减少于上游服务器的交互,加快接口/页面访问速度,减小服务器的压力。 12 | 13 | ## 功能特性 14 | - 多维度筛选请求流量,用户可根据请求流量中属性:应用、IP、API、上游、请求路径、请求方式等组合条件精准筛选流量。 15 | - 支持针对应用或IP获取缓存的响应数据。 16 | - 支持缓存有效时间设置。 17 | 18 | ## 更新日志 19 | ### V1.0(2023-4-30) 20 | - 插件上线 -------------------------------------------------------------------------------- /initialize/plugins/embed/strategy-cache.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/strategy-cache.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/strategy-cache.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "strategy-cache.apinto.com" 2 | name: "cache" 3 | cname: "数据缓存" 4 | resume: "通过缓存上游服务的静态资源,如:图片、静态页面等资源,减少于上游服务器的交互,加快接口/页面访问速度,减小服务器的压力。" 5 | version: "v1.0.7" 6 | icon: "logo.png" 7 | driver: "strategy-cache.apinto.com" 8 | type: 2 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: true 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: true 14 | front: serv-governance 15 | navigation: "navigation.strategy" 16 | group_id: "strategy" -------------------------------------------------------------------------------- /initialize/plugins/embed/strategy-fuse.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | 简单来说,用API的“出错比例”来表示这个API的健康状态,当这个比例值高于设定的阈值,API自动抛出异常,终止服务,这个过程就叫做自动熔断。 3 | 4 | API熔断后,可以保护数据库、上游服务等基础服务不受不健康的API的影响,减轻基础服务的压力,提高响应速度。 5 | ## 功能特性 6 | - 多维度筛选请求流量,用户可根据请求流量中属性:应用、IP、API、上游、请求路径、请求方式等组合条件精准筛选流量。 7 | - 支持熔断上游或上游的API。 8 | - 支持熔断自动恢复健康机制。 9 | - 对于正处于熔断期并符合筛选条件的请求流量,支持自定义响应内容。 10 | ## 更新日志 11 | ### V1.0(2023-4-30) 12 | - 插件上线 -------------------------------------------------------------------------------- /initialize/plugins/embed/strategy-fuse.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/strategy-fuse.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/strategy-fuse.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "strategy-fuse.apinto.com" 2 | name: "fuse" 3 | cname: "熔断" 4 | resume: 用API的"出错比例"来表示这个API的健康状态,,当这个比例值高于设定的阈值,API自动抛出异常,终止服务。 5 | version: "v1.0.7" 6 | icon: "logo.png" 7 | driver: "strategy-fuse.apinto.com" 8 | type: 2 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: true 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: true 14 | front: serv-governance 15 | navigation: "navigation.strategy" 16 | group_id: "strategy" -------------------------------------------------------------------------------- /initialize/plugins/embed/strategy-grey.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | 灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式。 3 | 4 | 在其上可以进行A/B testing,即让一部分用户继续用产品特性A,一部分用户开始用产品特性B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。 5 | 6 | 灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。 7 | 8 | ## 功能特性 9 | - 多维度筛选请求流量,用户可根据请求流量中属性:应用、IP、API、上游、请求路径、请求方式等组合条件精准筛选流量。 10 | - 支持按筛选的流量比例灰度到目标节点。 11 | - 支持匹配请求头或query参数的请求流量灰度到目标节点。 12 | ## 更新日志 13 | ### V1.0(2023-4-30) 14 | - 插件上线 -------------------------------------------------------------------------------- /initialize/plugins/embed/strategy-grey.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/strategy-grey.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/strategy-grey.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "strategy-grey.apinto.com" 2 | name: "grey" 3 | cname: "灰度发布" 4 | resume: "灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式。当前支持通过流量比例、请求规则对请求进行灰度代理。" 5 | version: "v1.0.7" 6 | icon: "logo.png" 7 | driver: "strategy-grey.apinto.com" 8 | type: 2 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: true 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: true 14 | front: serv-governance 15 | navigation: "navigation.strategy" 16 | group_id: "strategy" -------------------------------------------------------------------------------- /initialize/plugins/embed/strategy-traffic.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | 限制单位时间内请求API的次数或数据大小,当达到限制条件时返回预设的信息。可用于限制特定用户的API调用量,或者避免上游服务因为流量过大而崩溃。 3 | 4 | ## 功能特性 5 | - 灵活的流量控制:可根据应用、IP、API、上游、请求路径、请求方式等方式筛选出需要限制的流量,比如限制 6 | - 支持多种时间单位来限制流量:每小时、每分钟、每秒 7 | - 可限制单位时间内请求的次数或数据大小(MB) 8 | - 达到限制条件时,支持自定义响应内容,支持JSON、XML、自定义文本 9 | ## 更新日志 10 | ### V1.0(2023-4-30) 11 | - 插件上线 -------------------------------------------------------------------------------- /initialize/plugins/embed/strategy-traffic.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/strategy-traffic.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/strategy-traffic.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "strategy-traffic.apinto.com" 2 | name: "traffic" 3 | cname: "流量限制" 4 | resume: "限制单位时间内请求API的次数或数据大小,当达到限制条件时返回预设的信息。可用于限制特定用户的API调用量,或者避免上游服务因为流量过大而崩溃。" 5 | version: "v1.0.7" 6 | icon: "logo.png" 7 | driver: "strategy-traffic.apinto.com" 8 | type: 2 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: true 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: true 14 | front: serv-governance 15 | navigation: "navigation.strategy" 16 | group_id: "strategy" -------------------------------------------------------------------------------- /initialize/plugins/embed/strategy-visit.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | API访问权限是指通过Apinto网关对API接口的访问进行授权和限制的一种机制,可以控制哪些用户、IP、API可以访问API接口以及他们可以访问哪些资源和数据。 3 | 4 | 通过API访问权限,可以保证API接口的安全性和稳定性,防止未经授权的用户、IP、API对API接口进行恶意访问或者滥用资源导致系统宕机或故障。 5 | ## 功能特性 6 | - 多维度筛选请求流量,用户可根据请求流量中属性:应用、IP、API、上游、请求路径、请求方式等组合条件精准筛选流量。 7 | - 支持设置黑名单和白名单。 8 | ## 更新日志 9 | ### V1.0(2023-4-30) 10 | - 插件上线 -------------------------------------------------------------------------------- /initialize/plugins/embed/strategy-visit.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/strategy-visit.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/strategy-visit.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "strategy-visit.apinto.com" 2 | name: "visit" 3 | cname: "API访问权限" 4 | resume: "保证API接口的安全性和稳定性,防止未经授权的用户、IP、API对API接口进行恶意访问或者滥用资源导致系统宕机或故障。" 5 | version: "v1.0.7" 6 | icon: "logo.png" 7 | driver: "strategy-visit.apinto.com" 8 | type: 2 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: true 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: true 14 | front: serv-governance 15 | navigation: "navigation.strategy" 16 | group_id: "strategy" -------------------------------------------------------------------------------- /initialize/plugins/embed/upstream.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | 在系统架构中,我们可以通过河流理论来判断上下游,最好方法是想象一条河。 3 | 1. 下游的水肯定是来自上游的。 4 | 2. 如果有人破坏了河的下游部分,那将对上游没有影响。 5 | 3. 如果有人破坏了河的上游部分,这将影响下游,即不会得到任何水。 6 | 7 | 以订单服务调用为例 8 | 9 | ![](http://data.eolinker.com/course/aDDlSnc299d3dd7d3131812811d0b922d63f7ea5a7f60ab.png) 10 | 订单服务提供服务数据,是河流中的上游,软件A接受订单服务返回响应数据,作为河流中的下游。 11 | 12 | 为了保证上游服务的高可用及稳定性,一般来说,相同的上游服务会部署在多台机器/虚拟机中,通过增加机器/虚拟机的方式横向拓展,从而应对下游请求的流量高峰。 13 | 14 | 该插件将给Apinto网关配置上游服务信息,通过API绑定,实现完整转发流程。 15 | ## 功能特性 16 | - 支持配置负载均衡算法:IP Hash、带权轮询,合理分配上游服务压力,保证上游服务稳定性。 17 | - 支持引用环境变量,既统一了各环境各集群中上游服务的配置,又可以通过环境变量实现上游服务地址的差异化。 18 | - 支持会话保持,开启会话保持后,相同Session的请求将会转发到相同的上游服务地址,确保流程的连贯性。 19 | 20 | ## 更新日志 21 | ### V1.0(2023-4-30) 22 | - 插件上线 -------------------------------------------------------------------------------- /initialize/plugins/embed/upstream.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/upstream.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/variable.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | 环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数,是操作系统为了满足不同的应用场景预先在系统内预先设置的一大批全局变量。 3 | 4 | 环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性。此处定义的环境变量作用于网关集群中,在网关集群中全局生效。 5 | 6 | 项目部署环境一般可分为三种:生产环境,测试环境,开发环境,分别对应系统开发的三个阶段:开发->测试->上线。由于不同环境相互隔离的原因,不同环境一步部署了相同的上游服务业务,但上游服务地址一般是不同的。 7 | 8 | 我们可以通过环境变量的方式,在配置中引用相同的环境变量,设置不同环境不同集群中环境变量的值,以保证配置的一致性。 9 | ## 功能特性 10 | - 作用于网关集群,在网关集群中全局生效。 11 | - 支持在配置中引用环境变量,目前支持在上游服务中引用。 12 | ## 更新日志 13 | ### V1.0(2023-4-30) 14 | - 插件上线 -------------------------------------------------------------------------------- /initialize/plugins/embed/variable.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/variable.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/variable.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "variable.apinto.com" 2 | name: "variable" 3 | cname: "环境变量" 4 | resume: "通过环境变量的方式,在配置中引用相同的环境变量,设置不同环境不同集群中环境变量的值,以保证配置的一致性。" 5 | version: "v1.0.7" 6 | icon: "logo.png" 7 | driver: "variable.apinto.com" 8 | type: 1 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: false 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: true 14 | front: deploy 15 | navigation: "navigation.infrastructure" 16 | group_id: "core_module" -------------------------------------------------------------------------------- /initialize/plugins/embed/webhook.apinto.com/README.md: -------------------------------------------------------------------------------- 1 | ## 基本介绍 2 | Webhook(又名钩子) 是一个 API 概念,是微服务 API 的使用范式之一,也被称为反向 API,即前端不主动发送请求,完全由后端推送。 3 | 4 | 简单来说,Webhook 就是一个接收 HTTP POST(或GET,PUT,DELETE)的URL,一个实现了 Webhook 的 API 提供商就是在当事件发生的时候会向这个配置好的 URL 发送一条信息,与请求-响应式不同,使用 Webhook 你可以实时接受到变化。 5 | 6 | 在配置前,使用者需要提供一个Webhook API,支持对接企业微信、飞书、钉钉等常用办公软件等消息通知API。 7 | 当Apinto触发特定事件时,如请求失败次数告警,监控程序将会按照配置的Webhook规则,推送事件信息到目标地址,实时发送告警信息。 8 | ## 功能特性 9 | - 配置Webhook规则,包括请求地址、请求方式、请求体模版格式 10 | - 当监控触发告警事件时,监控程序按照Webhhok规则发送请求到目标地址,实时发送告警信息。 11 | - 通过Webhook的自定义请求体模版特性,对接微信、飞书、钉钉等常用办公软件的消息通知API, 12 | ## 更新日志 13 | ### V1.0(2023-4-30) 14 | - 插件上线 -------------------------------------------------------------------------------- /initialize/plugins/embed/webhook.apinto.com/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eolinker/apinto-dashboard/e64b242c25afdfcdae37b95f89c32802a7da5903/initialize/plugins/embed/webhook.apinto.com/logo.png -------------------------------------------------------------------------------- /initialize/plugins/embed/webhook.apinto.com/plugin.yml: -------------------------------------------------------------------------------- 1 | id: "webhook.apinto.com" 2 | name: "webhook" 3 | cname: "Webhook" 4 | resume: "自定义Webhook规则,当监控触发告警事件时,监控程序将会根据Webhook规则,推送信息到目标地址,实时发送告警信息。支持对接企业微信、飞书、钉钉等常用办公软件等消息通知API。" 5 | version: "v1.0.7" 6 | icon: "logo.png" 7 | driver: "webhook.apinto.com" 8 | type: 2 #0为框架模块 1为核心模块 2为内置模块 3为非内置 9 | auto: true 10 | is_can_disable: true 11 | is_can_uninstall: false 12 | visible_in_navigation: true 13 | visible_in_market: true 14 | front: system 15 | navigation: "navigation.system" 16 | group_id: "devops" -------------------------------------------------------------------------------- /module/access-reader.go: -------------------------------------------------------------------------------- 1 | package apinto_module 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | type AccessReaderHandler struct { 6 | accessOfPath map[string][]string 7 | } 8 | 9 | func (a *AccessReaderHandler) ReadAccess(ctx *gin.Context) { 10 | access, has := a.accessOfPath[ctx.FullPath()] 11 | if has { 12 | ctx.Set("access", access) 13 | } 14 | } 15 | 16 | type AccessReader struct { 17 | handler gin.HandlerFunc 18 | } 19 | 20 | func (a *AccessReader) ReadAccess(ctx *gin.Context) { 21 | if a.handler == nil { 22 | return 23 | } 24 | a.handler(ctx) 25 | } 26 | -------------------------------------------------------------------------------- /module/middleware.go: -------------------------------------------------------------------------------- 1 | package apinto_module 2 | 3 | import ( 4 | "context" 5 | "github.com/gin-gonic/gin" 6 | "net/http" 7 | ) 8 | 9 | func GenHandleMiddleware(handle func(ctx context.Context, request *MiddlewareRequest, writer MiddlewareResponseWriter)) gin.HandlerFunc { 10 | return func(ginCtx *gin.Context) { 11 | 12 | request, err := Read(ginCtx.Request) 13 | if err != nil { 14 | ginCtx.AbortWithError(http.StatusServiceUnavailable, err) 15 | return 16 | } 17 | 18 | writer := new(MiddlewareResponse) 19 | handle(ginCtx, request, writer) 20 | ginCtx.JSON(http.StatusOK, writer) 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /module/options.go: -------------------------------------------------------------------------------- 1 | package apinto_module 2 | 3 | type IFilterOptionHandlerSupport interface { 4 | FilterOptionHandler() []IFilterOptionHandler 5 | } 6 | type FilterOptionConfig struct { 7 | Title string 8 | 9 | Titles []OptionTitle 10 | Key string 11 | } 12 | type IFilterValue struct { 13 | } 14 | type IFilterOptionHandler interface { 15 | Name() string 16 | Config() FilterOptionConfig 17 | GetOptions(namespaceId int, keyword, groupUUID string, pageNum, pageSize int) ([]any, int) 18 | Labels(namespaceId int, values ...string) []string 19 | Label(namespaceId int, value string) string 20 | } 21 | 22 | type OptionTitle struct { 23 | Field string `json:"field"` 24 | Title string `json:"title"` 25 | } 26 | 27 | type IFilterOptionHandlerManager interface { 28 | ResetFilterOptionHandlers(handlers map[string]IFilterOptionHandler) 29 | } 30 | -------------------------------------------------------------------------------- /module/plugin.go: -------------------------------------------------------------------------------- 1 | package apinto_module 2 | 3 | type Plugin interface { 4 | CreateModule(name string, config interface{}) (Module, error) 5 | CheckConfig(name string, config interface{}) error 6 | GetPluginFrontend(moduleName string) string 7 | IsShowServer() bool 8 | } 9 | -------------------------------------------------------------------------------- /module/response-update_test.go: -------------------------------------------------------------------------------- 1 | package apinto_module 2 | 3 | import ( 4 | "fmt" 5 | _ "github.com/stretchr/testify/assert" 6 | ) 7 | 8 | func ExampleDoEvent() { 9 | type args struct { 10 | event string 11 | v any 12 | } 13 | type testCase struct { 14 | name string 15 | args args 16 | } 17 | tests := []testCase{ 18 | { 19 | name: "login", 20 | args: args{ 21 | event: "login", 22 | v: "username=a&nickname=b", 23 | }, 24 | }, 25 | } 26 | RegisterEventHandler("login", func(event string, v any) { 27 | fmt.Printf("get event %s:%s", event, v) 28 | }) 29 | for _, tt := range tests { 30 | 31 | DoEvent(tt.args.event, tt.args.v) 32 | 33 | } 34 | //output: get event login:username=a&nickname=b 35 | } 36 | -------------------------------------------------------------------------------- /module/simple.go: -------------------------------------------------------------------------------- 1 | package apinto_module 2 | -------------------------------------------------------------------------------- /modules/api/api-entry/api_history.go: -------------------------------------------------------------------------------- 1 | package api_entry 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/base/history-entry" 5 | "time" 6 | ) 7 | 8 | type ApiHistory struct { 9 | Id int 10 | ApiId int 11 | NamespaceId int 12 | OldValue ApiHistoryInfo 13 | NewValue ApiHistoryInfo 14 | OptType history_entry.OptType //1新增 2修改 3删除 15 | OptTime time.Time 16 | Operator int 17 | } 18 | 19 | type ApiHistoryInfo struct { 20 | Api API `json:"api"` 21 | Config APIVersionConfig `json:"config"` 22 | } 23 | -------------------------------------------------------------------------------- /modules/api/api-entry/api_runtime.go: -------------------------------------------------------------------------------- 1 | package api_entry 2 | 3 | import "time" 4 | 5 | type APIRuntime struct { 6 | Id int 7 | NamespaceId int 8 | ApiID int 9 | ClusterID int 10 | VersionID int 11 | IsOnline bool 12 | Disable bool 13 | Operator int 14 | CreateTime time.Time 15 | UpdateTime time.Time 16 | } 17 | -------------------------------------------------------------------------------- /modules/api/api-entry/api_stat.go: -------------------------------------------------------------------------------- 1 | package api_entry 2 | 3 | type APIStat struct { 4 | APIID int 5 | VersionID int 6 | } 7 | -------------------------------------------------------------------------------- /modules/api/api-entry/publish_history.go: -------------------------------------------------------------------------------- 1 | package api_entry 2 | 3 | import "time" 4 | 5 | type ApiPublishHistory struct { 6 | Id int 7 | VersionName string 8 | ClusterId int 9 | NamespaceId int 10 | Desc string 11 | VersionId int 12 | Target int 13 | APIVersionConfig 14 | OptType int 15 | Operator int 16 | OptTime time.Time 17 | } 18 | -------------------------------------------------------------------------------- /modules/api/service/api-driver.go: -------------------------------------------------------------------------------- 1 | package api_service 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/driver" 5 | "github.com/eolinker/apinto-dashboard/modules/api" 6 | ) 7 | 8 | const ( 9 | DriverApiHTTP = "http" 10 | DriverWebsocket = "websocket" 11 | ) 12 | 13 | type apiDriver struct { 14 | *driver.DriverManager[api.IAPIDriver] 15 | } 16 | 17 | func (d *apiDriver) List() []*api.APIDriverInfo { 18 | list := make([]*api.APIDriverInfo, 0) 19 | for name, _ := range d.Drivers() { 20 | list = append(list, &api.APIDriverInfo{ 21 | Name: name, 22 | }) 23 | } 24 | return list 25 | } 26 | 27 | func newAPIDriverManager() api.IAPIDriverManager { 28 | return &apiDriver{DriverManager: driver.CreateDriverManager[api.IAPIDriver]()} 29 | } 30 | -------------------------------------------------------------------------------- /modules/api/service/batch_online_api.go: -------------------------------------------------------------------------------- 1 | package api_service 2 | 3 | import ( 4 | "fmt" 5 | "github.com/eolinker/apinto-dashboard/cache" 6 | apimodel "github.com/eolinker/apinto-dashboard/modules/api/model" 7 | "time" 8 | ) 9 | 10 | type IBatchOnlineApiTaskCache interface { 11 | cache.IRedisCache[apimodel.BatchOnlineCheckTask, string] 12 | } 13 | 14 | type batchOnlineApiTaskCache struct { 15 | cache.IRedisCache[apimodel.BatchOnlineCheckTask, string] 16 | } 17 | 18 | func formatKey(token string) string { 19 | return fmt.Sprintf("batch_online_api_token:%s", token) 20 | } 21 | 22 | func newBatchOnlineTaskCache() IBatchOnlineApiTaskCache { 23 | 24 | return &batchOnlineApiTaskCache{ 25 | IRedisCache: cache.CreateRedisCache[apimodel.BatchOnlineCheckTask](time.Hour*8, formatKey), 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /modules/api/service/import_api_data.go: -------------------------------------------------------------------------------- 1 | package api_service 2 | 3 | import ( 4 | "fmt" 5 | "github.com/eolinker/apinto-dashboard/cache" 6 | apimodel "github.com/eolinker/apinto-dashboard/modules/api/model" 7 | "time" 8 | ) 9 | 10 | type IImportApiCache interface { 11 | cache.IRedisCache[apimodel.ImportAPIRedisData, string] 12 | } 13 | 14 | func importKey(token string) string { 15 | return fmt.Sprintf("import_api_token:%s", token) 16 | } 17 | 18 | func newImportCache() IImportApiCache { 19 | cacheInfo := cache.CreateRedisCache[apimodel.ImportAPIRedisData, string](time.Hour*8, importKey) 20 | 21 | return cacheInfo 22 | 23 | } 24 | -------------------------------------------------------------------------------- /modules/api/status-code/code.go: -------------------------------------------------------------------------------- 1 | package status_code 2 | 3 | const ( 4 | ApiModuleBaseErrCode = 101000 5 | ApiConfigBindErr = ApiModuleBaseErrCode + iota 6 | ApiSchemeNotExist 7 | ApiConfigCheckErr 8 | ApiRouterReduplicatedErr 9 | ApiGroupNotExistErr 10 | ApiServiceNotExistErr 11 | ApiTemplateNotExistErr 12 | ApiDataBaseErr 13 | ) 14 | -------------------------------------------------------------------------------- /modules/api/store/init.go: -------------------------------------------------------------------------------- 1 | package api_store 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/store" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func InitStoreDB(db store.IDB) { 9 | api := NewAPIStore(db) 10 | apiStat := NewAPIStatStore(db) 11 | apiVersion := newAPIVersionStore(db) 12 | apiHistory := newApiHistoryStore(db) 13 | apiPublishHistory := newApiPublishHistoryStore(db) 14 | 15 | bean.Injection(&api) 16 | bean.Injection(&apiStat) 17 | bean.Injection(&apiVersion) 18 | bean.Injection(&apiHistory) 19 | bean.Injection(&apiPublishHistory) 20 | } 21 | -------------------------------------------------------------------------------- /modules/application/application-entry/application_auth_publish.go: -------------------------------------------------------------------------------- 1 | package application_entry 2 | 3 | import "time" 4 | 5 | type AppPublishHistory struct { 6 | Id int 7 | VersionName string 8 | ClusterId int 9 | NamespaceId int 10 | Desc string 11 | VersionId int 12 | Target int 13 | ApplicationVersionConfig 14 | OptType int 15 | Operator int 16 | OptTime time.Time 17 | } 18 | -------------------------------------------------------------------------------- /modules/application/application-model/application_auth.go: -------------------------------------------------------------------------------- 1 | package application_model 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/application/application-entry" 5 | "time" 6 | ) 7 | 8 | type ApplicationAuth struct { 9 | *application_entry.ApplicationAuth 10 | Operator string 11 | ParamPosition string 12 | ParamName string 13 | ParamInfo string 14 | RuleInfo string //规则信息 15 | Config string //配置信息 16 | } 17 | 18 | type AppAuthItem struct { 19 | UUID string 20 | Title string 21 | Driver string 22 | Operator string 23 | HideCredential bool 24 | ExpireTime int64 25 | UpdateTime time.Time 26 | } 27 | 28 | type AuthDetailItem struct { 29 | Key string `json:"key"` 30 | Value string `json:"value"` 31 | } 32 | -------------------------------------------------------------------------------- /modules/application/application-service/auth.go: -------------------------------------------------------------------------------- 1 | package application_service 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/driver" 5 | "github.com/eolinker/apinto-dashboard/modules/application" 6 | ) 7 | 8 | type authDriver struct { 9 | *driver.DriverManager[application.IAuthDriver] 10 | } 11 | 12 | func newAuthDriverManager() application.IAuthDriverManager { 13 | return &authDriver{DriverManager: driver.CreateDriverManager[application.IAuthDriver]()} 14 | } 15 | 16 | func (d *authDriver) List() []*driver.DriverInfo { 17 | list := make([]*driver.DriverInfo, 0) 18 | for name, value := range d.Drivers() { 19 | list = append(list, &driver.DriverInfo{ 20 | Name: name, 21 | Render: value.Render(), 22 | }) 23 | } 24 | return list 25 | } 26 | -------------------------------------------------------------------------------- /modules/application/application-service/driver.go: -------------------------------------------------------------------------------- 1 | package application_service 2 | 3 | const ( 4 | DriverBasic = "basic" 5 | DriverApikey = "apikey" 6 | DriverAKsK = "aksk" 7 | DriverJwt = "jwt" 8 | ) 9 | -------------------------------------------------------------------------------- /modules/application/application-service/init.go: -------------------------------------------------------------------------------- 1 | package application_service 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/application/driver" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func init() { 9 | apikey := driver.CreateApikey() 10 | aksk := driver.CreateAkSk() 11 | jwt := driver.CreateJwt() 12 | basic := driver.CreateBasic() 13 | 14 | authDriverManager := newAuthDriverManager() 15 | authDriverManager.RegisterDriver(DriverApikey, apikey) 16 | authDriverManager.RegisterDriver(DriverAKsK, aksk) 17 | authDriverManager.RegisterDriver(DriverJwt, jwt) 18 | authDriverManager.RegisterDriver(DriverBasic, basic) 19 | 20 | bean.Injection(&authDriverManager) 21 | 22 | application := newApplicationService() 23 | 24 | bean.Injection(&application) 25 | } 26 | -------------------------------------------------------------------------------- /modules/application/application-store/init.go: -------------------------------------------------------------------------------- 1 | package application_store 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/store" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func init() { 9 | store.RegisterStore(func(db store.IDB) { 10 | application := newApplicationStore(db) 11 | applicationStat := newApplicationStatStore(db) 12 | applicationVersion := newApplicationVersionStore(db) 13 | applicationAuth := newApplicationAuthStore(db) 14 | applicationHistory := newApplicationHistoryStore(db) 15 | appPublishHistory := newAppPublishHistoryStore(db) 16 | 17 | bean.Injection(&application) 18 | bean.Injection(&applicationVersion) 19 | bean.Injection(&applicationStat) 20 | bean.Injection(&applicationAuth) 21 | bean.Injection(&applicationHistory) 22 | bean.Injection(&appPublishHistory) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /modules/application/driver/common.go: -------------------------------------------------------------------------------- 1 | package driver 2 | 3 | type AuthConfig struct { 4 | AkSkConfig 5 | JwtConfig 6 | ApikeyConfig 7 | BasicConfig 8 | } 9 | -------------------------------------------------------------------------------- /modules/audit/audit-service/init.go: -------------------------------------------------------------------------------- 1 | package audit_service 2 | 3 | import "github.com/eolinker/eosc/common/bean" 4 | 5 | func init() { 6 | auditLog := newAuditLogService() 7 | bean.Injection(&auditLog) 8 | } 9 | -------------------------------------------------------------------------------- /modules/audit/audit-store/init.go: -------------------------------------------------------------------------------- 1 | package audit_store 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/store" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func init() { 9 | store.RegisterStore(func(db store.IDB) { 10 | auditLog := newAuditLogStore(db) 11 | bean.Injection(&auditLog) 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /modules/audit/audit.go: -------------------------------------------------------------------------------- 1 | package audit 2 | 3 | import ( 4 | "context" 5 | "github.com/eolinker/apinto-dashboard/modules/audit/audit-model" 6 | "time" 7 | ) 8 | 9 | type IAuditLogService interface { 10 | GetLogsList(ctx context.Context, namespaceID, operateType int, kind, keyword string, start, end int64, pageNum, pageSize int) ([]*audit_model.LogListItem, int, error) 11 | GetLogDetail(ctx context.Context, logID int) ([]*audit_model.LogDetailArg, error) 12 | Log(namespace int, userId int, operate int, kind string, url, object, ip, userAgent, body, err string, start, end time.Time) 13 | } 14 | -------------------------------------------------------------------------------- /modules/base/env-model/cluster_enum.go: -------------------------------------------------------------------------------- 1 | package env_model 2 | 3 | import "fmt" 4 | 5 | type EnumEnv int 6 | 7 | const ( 8 | EnumEnvNone = iota 9 | EnumEnvPRO 10 | EnumEnvFAT 11 | EnumEnvDEV 12 | EnumEnvUAT 13 | EnumEnvAll 14 | ) 15 | 16 | var ( 17 | enumValueNames = map[EnumEnv]string{ 18 | EnumEnvNone: "NONE", 19 | EnumEnvPRO: "PRO", 20 | EnumEnvFAT: "FAT", 21 | EnumEnvDEV: "DEV", 22 | EnumEnvUAT: "UAT", 23 | } 24 | EnumValueList = []EnumEnv{EnumEnvPRO, EnumEnvFAT, EnumEnvDEV, EnumEnvUAT} 25 | ) 26 | 27 | type EnumEnvOut struct { 28 | Name string `json:"name"` 29 | Value EnumEnv `json:"value"` 30 | } 31 | 32 | func (e EnumEnv) MarshalJSON() ([]byte, error) { 33 | return []byte(fmt.Sprint("\"", e.String(), "\"")), nil 34 | } 35 | 36 | func (e EnumEnv) String() string { 37 | if e >= EnumEnvAll { 38 | return "unknown" 39 | } 40 | return enumValueNames[e] 41 | } 42 | -------------------------------------------------------------------------------- /modules/base/frontend-model/frontend.go: -------------------------------------------------------------------------------- 1 | package frontend_model 2 | 3 | type RouterName string 4 | 5 | var ( 6 | RouterNameClusterVariable RouterName = "deploy/cluster/content" //cluster_name 7 | RouterNameDiscoveryOnline RouterName = "upstream/serv-discovery/content" //discovery_name 8 | RouterNameServiceOnline RouterName = "template/upstream" 9 | RouterNameTemplateOnline RouterName = "router/plugin-template/content" 10 | RouterNameClusterPlugin RouterName = "deploy/cluster/content/plugin" 11 | ) 12 | 13 | type Router struct { 14 | Name RouterName `json:"name"` 15 | Params map[string]string `json:"params"` 16 | Msg string `json:"msg,omitempty"` 17 | } 18 | -------------------------------------------------------------------------------- /modules/base/locker-service/init.go: -------------------------------------------------------------------------------- 1 | package locker_service 2 | 3 | import "github.com/eolinker/eosc/common/bean" 4 | 5 | func init() { 6 | lockAsynService := NewAsynLockService() 7 | lockSyncService := NewSyncLockService() 8 | bean.Injection(&lockAsynService) 9 | bean.Injection(&lockSyncService) 10 | } 11 | -------------------------------------------------------------------------------- /modules/base/quote-store/init.go: -------------------------------------------------------------------------------- 1 | package quote_store 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/store" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func init() { 9 | store.RegisterStore(func(db store.IDB) { 10 | quote := newQuoteStore(db) 11 | bean.Injection("e) 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /modules/base/stat-entry/stat.go: -------------------------------------------------------------------------------- 1 | package stat_entry 2 | 3 | // Stat 最新版本关联表 4 | type Stat struct { 5 | ID int `gorm:"type:int(11);size:11;not null;auto_increment;primary_key;column:id;comment:主键ID"` 6 | Kind string `gorm:"size:20;not null;column:kind;uniqueIndex:kind;comment:根据kind区分是哪个表的ID"` 7 | Tag int `gorm:"type:int(11);size:11;not null;column:target;uniqueIndex:kind"` 8 | Version int `gorm:"type:int(11);size:11;not null;column:version;comment:版本ID"` 9 | } 10 | 11 | func (s *Stat) IdValue() int { 12 | return s.ID 13 | } 14 | 15 | func (*Stat) TableName() string { 16 | return "stat" 17 | } 18 | -------------------------------------------------------------------------------- /modules/cluster/cluster-dto/cluster_certificate.go: -------------------------------------------------------------------------------- 1 | package cluster_dto 2 | 3 | type ClusterCertificateInput struct { 4 | Key string `json:"key"` 5 | Pem string `json:"pem"` 6 | } 7 | 8 | type ClusterCertificateOut struct { 9 | Id int `json:"id"` 10 | ClusterId int `json:"cluster_id"` 11 | Name string `json:"name"` 12 | DNSName []string `json:"dns_name"` 13 | OperatorName string `json:"operator"` 14 | ValidTime string `json:"valid_time"` 15 | CreateTime string `json:"create_time"` 16 | UpdateTime string `json:"update_time"` 17 | } 18 | -------------------------------------------------------------------------------- /modules/cluster/cluster-dto/cluster_node.go: -------------------------------------------------------------------------------- 1 | package cluster_dto 2 | 3 | import "github.com/eolinker/apinto-dashboard/enum" 4 | 5 | type ClusterNode struct { 6 | Name string `json:"name"` 7 | ServiceAddr string `json:"service_addr"` 8 | AdminAddr string `json:"admin_addr"` 9 | Status enum.ClusterNodeStatus `json:"status"` 10 | } 11 | 12 | type ClusterNodeSimple struct { 13 | Name string `json:"name"` 14 | } 15 | type ClusterNodeInput struct { 16 | Source string `json:"source"` 17 | ClusterAddr string `json:"cluster_addr"` 18 | } 19 | -------------------------------------------------------------------------------- /modules/cluster/cluster-entry/cluster_config_runtime.go: -------------------------------------------------------------------------------- 1 | package cluster_entry 2 | 3 | import "time" 4 | 5 | type ClusterConfigRuntime struct { 6 | Id int 7 | NamespaceId int 8 | ConfigID int 9 | ClusterId int 10 | IsOnline bool 11 | Operator int 12 | CreateTime time.Time 13 | UpdateTime time.Time 14 | } 15 | -------------------------------------------------------------------------------- /modules/cluster/cluster-model/cluster.go: -------------------------------------------------------------------------------- 1 | package cluster_model 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/cluster/cluster-entry" 5 | ) 6 | 7 | type Cluster struct { 8 | *cluster_entry.Cluster 9 | Status int //1正常 2部分正常 3异常 10 | } 11 | 12 | //func (c *Cluster) GetName() string { 13 | // return c.Name 14 | //} 15 | // 16 | //func (c *Cluster) GetAddr() string { 17 | // return c.Addr 18 | //} 19 | 20 | type ClusterSimple struct { 21 | Name string `json:"name"` 22 | Title string `json:"title"` 23 | Env string `json:"env"` 24 | } 25 | -------------------------------------------------------------------------------- /modules/cluster/cluster-model/cluster_certificate.go: -------------------------------------------------------------------------------- 1 | package cluster_model 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/cluster/cluster-entry" 5 | ) 6 | 7 | type ClusterCertificate struct { 8 | *cluster_entry.ClusterCertificate 9 | ClusterName string 10 | OperatorName string 11 | } 12 | 13 | type Certificate struct { 14 | ID int `json:"id"` 15 | Name string `json:"name"` 16 | DnsName []string `json:"dns_name"` 17 | Key string `json:"key"` 18 | Pem string `json:"pem"` 19 | ValidTime string `json:"valid_time"` 20 | } 21 | -------------------------------------------------------------------------------- /modules/cluster/cluster-service/node_cache.go: -------------------------------------------------------------------------------- 1 | package cluster_service 2 | 3 | import ( 4 | "fmt" 5 | "github.com/eolinker/apinto-dashboard/cache" 6 | "github.com/eolinker/apinto-dashboard/modules/cluster/cluster-model" 7 | "time" 8 | ) 9 | 10 | type INodeCache interface { 11 | cache.IRedisCache[[]*cluster_model.Node, int] 12 | } 13 | 14 | func installedCacheKey(clusterId int) string { 15 | return fmt.Sprintf("cluster_%d_nodes", clusterId) 16 | } 17 | 18 | func newINodeCache() INodeCache { 19 | return cache.CreateRedisCache[[]*cluster_model.Node, int](5*time.Minute, installedCacheKey) 20 | } 21 | -------------------------------------------------------------------------------- /modules/core/controller/env.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | apinto_module "github.com/eolinker/apinto-dashboard/module" 5 | env_controller "github.com/eolinker/apinto-dashboard/modules/base/env-controller" 6 | "net/http" 7 | ) 8 | 9 | func envEnumRouters() apinto_module.RoutersInfo { 10 | ec := env_controller.NewEnumController() 11 | return apinto_module.RoutersInfo{ 12 | { 13 | Method: http.MethodGet, 14 | Path: "/api/enum/envs", 15 | HandlerFunc: []apinto_module.HandlerFunc{ec.GetEnv}, 16 | }, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /modules/core/controller/expire.go: -------------------------------------------------------------------------------- 1 | package controller 2 | -------------------------------------------------------------------------------- /modules/core/controller/report.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/controller" 5 | "github.com/eolinker/apinto-dashboard/report" 6 | "github.com/gin-gonic/gin" 7 | "net/http" 8 | ) 9 | 10 | func (m *Module) reportStatus(ginCtx *gin.Context) { 11 | consoleId, nodes, need := report.NeedReport() 12 | if !need { 13 | ginCtx.JSON(http.StatusOK, controller.NewSuccessResult(map[string]interface{}{ 14 | "report": "no", 15 | })) 16 | 17 | return 18 | } 19 | ginCtx.JSON(http.StatusOK, controller.NewSuccessResult(map[string]interface{}{ 20 | "report": "yes", 21 | "id": consoleId, 22 | "nodes": nodes, 23 | })) 24 | 25 | } 26 | 27 | func (m *Module) updateReport(ginCtx *gin.Context) { 28 | report.UpdateReport() 29 | ginCtx.JSON(http.StatusOK, controller.NewSuccessResult(nil)) 30 | 31 | } 32 | -------------------------------------------------------------------------------- /modules/core/model/navigation.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | type Navigation struct { 4 | Title string `json:"title"` 5 | Icon string `json:"icon"` 6 | //IconType string `json:"icon_type"` 7 | Modules []*Module `json:"modules"` 8 | Default string `json:"default"` 9 | } 10 | 11 | type Module struct { 12 | Name string `json:"name"` 13 | Title string `json:"title"` 14 | //Type string `json:"type"` 15 | Path string `json:"path"` 16 | } 17 | -------------------------------------------------------------------------------- /modules/core/service.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "context" 5 | "github.com/eolinker/apinto-dashboard/modules/core/model" 6 | "github.com/gin-gonic/gin" 7 | "net/http" 8 | ) 9 | 10 | type ICore interface { 11 | http.Handler 12 | ResetVersion(version string) 13 | ReloadModule() error 14 | CheckNewModule(uuid, name, driver string, define, config interface{}) error 15 | HasModule(module string, path string) bool 16 | } 17 | 18 | type EngineCreate interface { 19 | CreateEngine() (engine *gin.Engine) 20 | } 21 | type INavigationService interface { 22 | List(ctx context.Context) ([]*model.Navigation, map[string]string, error) 23 | } 24 | -------------------------------------------------------------------------------- /modules/core/service/init.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | apinto_module "github.com/eolinker/apinto-dashboard/module" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func init() { 9 | navigationService := newNavigationService() 10 | bean.Injection(&navigationService) 11 | 12 | providerService := NewProviderService() 13 | 14 | var iProviders apinto_module.IProviders = providerService 15 | bean.Injection(&iProviders) 16 | iCore := NewService(providerService) 17 | bean.Injection(&iCore) 18 | 19 | } 20 | -------------------------------------------------------------------------------- /modules/dynamic/dynamic-dto/cluster.go: -------------------------------------------------------------------------------- 1 | package dynamic_dto 2 | 3 | type Cluster struct { 4 | Cluster []string `json:"cluster"` 5 | } 6 | -------------------------------------------------------------------------------- /modules/dynamic/dynamic-entry/dynamic_publish_history.go: -------------------------------------------------------------------------------- 1 | package dynamic_entry 2 | 3 | import "time" 4 | 5 | type DynamicPublishHistory struct { 6 | Id int 7 | VersionName string 8 | ClusterId int 9 | NamespaceId int 10 | Target int 11 | Desc string 12 | VersionId int 13 | Publish *DynamicPublishConfig //此次发布的数据 14 | OptType int 15 | Operator int 16 | CreateTime time.Time 17 | } 18 | -------------------------------------------------------------------------------- /modules/dynamic/dynamic-entry/dynamic_quote.go: -------------------------------------------------------------------------------- 1 | package dynamic_entry 2 | 3 | type DynamicQuote struct { 4 | Id int `gorm:"column:id;type:INT(11);AUTO_INCREMENT;NOT NULL;comment:主键ID"` 5 | Namespace int `gorm:"column:namespace;type:INT(11);NOT NULL;comment:工作空间"` 6 | Source string `gorm:"column:source;type:VARCHAR(255);NOT NULL;comment:源name"` 7 | Target string `gorm:"column:target;type:VARCHAR(255);NOT NULL;comment:依赖name"` 8 | } 9 | 10 | func (d *DynamicQuote) TableName() string { 11 | return "dynamic_quote" 12 | } 13 | 14 | func (d *DynamicQuote) IdValue() int { 15 | return d.Id 16 | } 17 | -------------------------------------------------------------------------------- /modules/dynamic/dynamic-model/render.go: -------------------------------------------------------------------------------- 1 | package dynamic_model 2 | 3 | type DynamicModuleRender struct { 4 | *DynamicBasicInfo 5 | Render map[string]interface{} `json:"render"` 6 | } 7 | -------------------------------------------------------------------------------- /modules/dynamic/dynamic-service/init.go: -------------------------------------------------------------------------------- 1 | package dynamic_service 2 | 3 | import "github.com/eolinker/eosc/common/bean" 4 | 5 | func init() { 6 | ds := newDynamicService() 7 | bean.Injection(&ds) 8 | } 9 | -------------------------------------------------------------------------------- /modules/dynamic/dynamic-store/dynamic_quote.go: -------------------------------------------------------------------------------- 1 | package dynamic_store 2 | 3 | import ( 4 | dynamic_entry "github.com/eolinker/apinto-dashboard/modules/dynamic/dynamic-entry" 5 | "github.com/eolinker/apinto-dashboard/store" 6 | ) 7 | 8 | type IDynamicQuoteStore interface { 9 | store.IBaseStore[dynamic_entry.DynamicQuote] 10 | } 11 | 12 | type dynamicQuoteStore struct { 13 | *store.BaseStore[dynamic_entry.DynamicQuote] 14 | } 15 | 16 | func newDynamicQuoteStore(db store.IDB) IDynamicQuoteStore { 17 | return &dynamicQuoteStore{BaseStore: store.CreateStore[dynamic_entry.DynamicQuote](db)} 18 | } 19 | -------------------------------------------------------------------------------- /modules/dynamic/dynamic-store/init.go: -------------------------------------------------------------------------------- 1 | package dynamic_store 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/store" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | var ( 9 | kind = "dynamic_module" 10 | ) 11 | 12 | func init() { 13 | store.RegisterStore(func(db store.IDB) { 14 | dynamic := newDynamicStore(db) 15 | dynamicQuote := newDynamicQuoteStore(db) 16 | dynamicPublishHistory := NewDynamicPublishHistoryStore(db, kind) 17 | dynamicPublishVersion := NewDynamicPublishVersionStore(db, kind) 18 | bean.Injection(&dynamic) 19 | bean.Injection(&dynamicQuote) 20 | bean.Injection(&dynamicPublishHistory) 21 | bean.Injection(&dynamicPublishVersion) 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /modules/email/dto/email.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type EmailInput struct { 4 | Uuid string `json:"uuid"` 5 | SmtpUrl string `json:"smtp_url"` 6 | SmtpPort int `json:"smtp_port"` 7 | Protocol string `json:"protocol"` 8 | Email string `json:"email"` 9 | Account string `json:"account"` 10 | Password string `json:"password"` 11 | } 12 | 13 | type EmailOutput struct { 14 | Uuid string `json:"uuid"` 15 | SmtpUrl string `json:"smtp_url"` 16 | SmtpPort int `json:"smtp_port"` 17 | Protocol string `json:"protocol"` 18 | Email string `json:"email"` 19 | Account string `json:"account"` 20 | Password string `json:"password"` 21 | } 22 | -------------------------------------------------------------------------------- /modules/group/group-model/common_group.go: -------------------------------------------------------------------------------- 1 | package group_model 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/group/group-entry" 5 | ) 6 | 7 | type CommonGroupRoot struct { 8 | UUID string 9 | Name string 10 | CommonGroup []*CommonGroup 11 | } 12 | 13 | type CommonGroup struct { 14 | Group *group_entry.CommonGroup 15 | Subgroup []*CommonGroup 16 | } 17 | 18 | type CommonGroupApi struct { 19 | Path string 20 | PathLabel string 21 | Name string 22 | UUID string 23 | Methods []string 24 | GroupUUID string 25 | } 26 | 27 | type CommonGroupBasic struct { 28 | Uuid string 29 | Type string 30 | TagID int 31 | Name string 32 | ParentId int 33 | Sort int 34 | } 35 | -------------------------------------------------------------------------------- /modules/group/group-service/init.go: -------------------------------------------------------------------------------- 1 | package group_service 2 | 3 | import "github.com/eolinker/eosc/common/bean" 4 | 5 | func init() { 6 | group := newCommonGroupService() 7 | 8 | bean.Injection(&group) 9 | } 10 | -------------------------------------------------------------------------------- /modules/group/group-store/init.go: -------------------------------------------------------------------------------- 1 | package group_store 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/store" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func init() { 9 | store.RegisterStore(func(db store.IDB) { 10 | commonGroup := newCommonGroupStore(db) 11 | 12 | bean.Injection(&commonGroup) 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /modules/grpc-service/service/cache.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/cache" 5 | grpc_service "github.com/eolinker/apinto-dashboard/grpc-service" 6 | "time" 7 | ) 8 | 9 | type INavigationModulesCache interface { 10 | cache.IRedisCache[grpc_service.NavigationModulesResp, string] 11 | } 12 | 13 | func navigationModulesCacheKey(string) string { 14 | return "navigation_modules" 15 | } 16 | 17 | func newNavigationModulesCache() INavigationModulesCache { 18 | return cache.CreateRedisCache[grpc_service.NavigationModulesResp](time.Hour, navigationModulesCacheKey) 19 | } 20 | -------------------------------------------------------------------------------- /modules/grpc-service/service/error.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | type SendMsgError struct { 4 | UUID string `json:"uuid"` 5 | NoticeChannelUUID string `json:"notice_channel_uuid"` 6 | Msg string `json:"msg"` 7 | } 8 | -------------------------------------------------------------------------------- /modules/grpc-service/service/init.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "github.com/eolinker/eosc/common/bean" 5 | ) 6 | 7 | func init() { 8 | iInstalledCache := newNavigationModulesCache() 9 | bean.Injection(&iInstalledCache) 10 | 11 | } 12 | -------------------------------------------------------------------------------- /modules/log/dto/arg.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package dto 10 | 11 | type Args string 12 | -------------------------------------------------------------------------------- /modules/log/dto/output.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package dto 10 | 11 | type Output struct { 12 | Name string `json:"name"` 13 | TailKey string `json:"tail"` 14 | Files []File `json:"files"` 15 | } 16 | type File struct { 17 | File string `json:"file,omitempty"` 18 | Size string `json:"size,omitempty"` 19 | Mod string `json:"mod,omitempty"` 20 | Key string `json:"key,omitempty"` 21 | } 22 | -------------------------------------------------------------------------------- /modules/log/module/conn.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package module 6 | 7 | import ( 8 | "bufio" 9 | "net" 10 | ) 11 | 12 | // The Conn type represents a WebSocket connection. 13 | type Conn struct { 14 | net.Conn 15 | readBuf *bufio.Reader 16 | } 17 | 18 | func (c *Conn) Read(p []byte) (int, error) { 19 | return c.readBuf.Read(p) 20 | } 21 | -------------------------------------------------------------------------------- /modules/module-plugin/entry/module_plugin_package.go: -------------------------------------------------------------------------------- 1 | package entry 2 | 3 | type ModulePluginPackage struct { 4 | Id int `gorm:"column:id;type:int(11);autoIncrement:false;primary_key;comment:模块插件表的主键ID" json:"id"` 5 | Package []byte `gorm:"column:package;type:mediumblob;not null;comment:安装包" json:"package"` 6 | } 7 | 8 | func (*ModulePluginPackage) TableName() string { 9 | return "module_plugin_package" 10 | } 11 | 12 | func (c *ModulePluginPackage) IdValue() int { 13 | return c.Id 14 | } 15 | -------------------------------------------------------------------------------- /modules/module-plugin/entry/module_plugin_resources.go: -------------------------------------------------------------------------------- 1 | package entry 2 | 3 | type PluginResources struct { 4 | ID int `gorm:"type:int(11);size:11;not null;primary_key;column:id;comment:主键ID"` 5 | Uuid string `gorm:"uniqueIndex:uuid;index;not null;size:36;column:uuid;comment:插件id"` 6 | Resources []byte `gorm:"type:mediumblob;serializer:json;column:resources"` 7 | } 8 | 9 | func (c *PluginResources) TableName() string { 10 | return "module_plugin_resources" 11 | } 12 | 13 | func (c *PluginResources) IdValue() int { 14 | return c.ID 15 | } 16 | -------------------------------------------------------------------------------- /modules/module-plugin/model/plugin_front.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | type PluginInstalledStatus struct { 4 | Installed bool 5 | } 6 | -------------------------------------------------------------------------------- /modules/module-plugin/service/enum.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | const ( 4 | pluginGroupOther = "other" 5 | 6 | // statusPluginDisable 插件停用枚举值 7 | statusPluginDisable = 1 8 | // statusPluginEnable 插件启用枚举值 9 | statusPluginEnable = 2 10 | 11 | // pluginTypeFrame 框架插件类型 不可卸载,不可停用,不显示在插件广场 12 | pluginTypeFrame = 0 13 | // pluginTypeCore 核心插件类型 不可卸载,不可停用 14 | pluginTypeCore = 1 15 | // pluginTypeInner 内置插件类型 不可卸载 16 | pluginTypeInner = 2 17 | // pluginTypeNotInner 非内置插件类型 18 | pluginTypeNotInner = 3 19 | 20 | pluginDriverRemote = "remote" 21 | pluginDriverLocal = "local" 22 | ) 23 | -------------------------------------------------------------------------------- /modules/module-plugin/service/error.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrModulePluginNotFound = errors.New("插件不存在") 7 | ErrModulePluginDriverNotFound = errors.New("插件驱动不存在") 8 | ErrModulePluginInstalled = errors.New("插件已安装") 9 | ErrModulePluginHasDisabled = errors.New("插件已停用") 10 | ErrModulePluginCantDisabled = errors.New("插件不可以停用") 11 | ErrModulePluginHasEnabled = errors.New("插件已启用") 12 | ) 13 | -------------------------------------------------------------------------------- /modules/module-plugin/service/init.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "github.com/eolinker/eosc/common/bean" 5 | ) 6 | 7 | func init() { 8 | iModulePluginService := newModulePluginService() 9 | iModulePlugin := newModulePlugin() 10 | bean.Injection(&iModulePluginService) 11 | bean.Injection(&iModulePlugin) 12 | iInstalledCache := newIInstalledCache() 13 | iNavigationModulesCache := newNavigationModulesCache() 14 | bean.Injection(&iInstalledCache) 15 | bean.Injection(&iNavigationModulesCache) 16 | 17 | } 18 | -------------------------------------------------------------------------------- /modules/module-plugin/service/installed_cache.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "fmt" 5 | "github.com/eolinker/apinto-dashboard/cache" 6 | "github.com/eolinker/apinto-dashboard/modules/module-plugin/model" 7 | "time" 8 | ) 9 | 10 | type IInstalledCache interface { 11 | cache.IRedisCache[model.PluginInstalledStatus, string] 12 | } 13 | 14 | func installedCacheKey(pluginID string) string { 15 | return fmt.Sprintf("plugin_installed_%s", pluginID) 16 | } 17 | 18 | func newIInstalledCache() IInstalledCache { 19 | return cache.CreateRedisCache[model.PluginInstalledStatus, string](time.Hour, installedCacheKey) 20 | } 21 | -------------------------------------------------------------------------------- /modules/module-plugin/service/navigation_modules_cache.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/cache" 5 | module_plugin "github.com/eolinker/apinto-dashboard/modules/module-plugin" 6 | "github.com/eolinker/apinto-dashboard/modules/module-plugin/entry" 7 | "time" 8 | ) 9 | 10 | func newNavigationModulesCache() module_plugin.INavigationModulesCache { 11 | return cache.CreateRedisCacheNoKey[entry.EnabledModule](10*time.Minute, "navigationModulesCacheKey") 12 | 13 | } 14 | -------------------------------------------------------------------------------- /modules/module-plugin/store/init.go: -------------------------------------------------------------------------------- 1 | package store 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/store" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func init() { 9 | store.RegisterStore(func(db store.IDB) { 10 | modulePlugin := newModulePluginStore(db) 11 | pluginEnable := newModulePluginEnableStore(db) 12 | modulePluginResources := newPluginResourcesStore(db) 13 | pluginPackage := newModulePluginPackageStore(db) 14 | 15 | bean.Injection(&modulePlugin) 16 | bean.Injection(&pluginEnable) 17 | bean.Injection(&modulePluginResources) 18 | bean.Injection(&pluginPackage) 19 | 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /modules/module-plugin/store/module_plugin_resources.go: -------------------------------------------------------------------------------- 1 | package store 2 | 3 | import ( 4 | "context" 5 | "github.com/eolinker/apinto-dashboard/modules/module-plugin/entry" 6 | "github.com/eolinker/apinto-dashboard/store" 7 | ) 8 | 9 | type IPluginResources interface { 10 | store.IBaseStore[entry.PluginResources] 11 | GetByUUID(ctx context.Context, uuid string) (*entry.PluginResources, error) 12 | } 13 | 14 | type pluginResources struct { 15 | store.IBaseStore[entry.PluginResources] 16 | } 17 | 18 | func (c *pluginResources) GetByUUID(ctx context.Context, uuid string) (*entry.PluginResources, error) { 19 | return c.IBaseStore.First(ctx, map[string]interface{}{"uuid": uuid}) 20 | } 21 | 22 | func newPluginResourcesStore(db store.IDB) IPluginResources { 23 | 24 | return &pluginResources{IBaseStore: store.CreateStore[entry.PluginResources](db)} 25 | } 26 | -------------------------------------------------------------------------------- /modules/namespace/namespace-entry/namespace.go: -------------------------------------------------------------------------------- 1 | package namespace_entry 2 | 3 | import "time" 4 | 5 | // Namespace 工作空间 6 | type Namespace struct { 7 | Id int `gorm:"type:int(11);size:11;not null;auto_increment;primary_key;column:id;comment:主键ID"` 8 | Name string `gorm:"size:255;not null;column:name;comment:名称"` 9 | CreateTime time.Time `gorm:"type:timestamp;NOT NULL;DEFAULT:CURRENT_TIMESTAMP;column:create_time;comment:创建时间"` 10 | } 11 | 12 | func (Namespace) TableName() string { 13 | return "namespace" 14 | } 15 | -------------------------------------------------------------------------------- /modules/namespace/namespace-model/namespace.go: -------------------------------------------------------------------------------- 1 | package namespace_model 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type Namespace struct { 8 | Id int 9 | Name string 10 | CreateTime time.Time 11 | } 12 | -------------------------------------------------------------------------------- /modules/namespace/namespace-store/init.go: -------------------------------------------------------------------------------- 1 | package namespace_store 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/store" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func init() { 9 | store.RegisterStore(func(db store.IDB) { 10 | namespace := newNamespaceStore(db) 11 | 12 | bean.Injection(&namespace) 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /modules/namespace/service.go: -------------------------------------------------------------------------------- 1 | package namespace 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/namespace/namespace-model" 5 | ) 6 | 7 | type INamespaceService interface { 8 | GetByName(namespace string) (*namespace_model.Namespace, error) 9 | GetById(namespaceId int) (*namespace_model.Namespace, error) 10 | GetAll() ([]*namespace_model.Namespace, error) 11 | } 12 | -------------------------------------------------------------------------------- /modules/navigation/navigation-model/navigation.go: -------------------------------------------------------------------------------- 1 | package navigation_model 2 | 3 | type Navigation struct { 4 | Uuid string `json:"uuid" yaml:"id"` 5 | Name string `json:"-" yaml:"name"` 6 | Title string `json:"title" yaml:"cname"` 7 | Icon string `json:"icon" yaml:"icon"` 8 | Quick bool `json:"quick" yaml:"quick"` 9 | } 10 | -------------------------------------------------------------------------------- /modules/navigation/navigation-service/init.go: -------------------------------------------------------------------------------- 1 | package navigation_service 2 | 3 | import ( 4 | "github.com/eolinker/eosc/common/bean" 5 | ) 6 | 7 | func init() { 8 | service := newNavigationService() 9 | bean.Injection(&service) 10 | } 11 | -------------------------------------------------------------------------------- /modules/navigation/navigation.go: -------------------------------------------------------------------------------- 1 | package navigation 2 | 3 | import ( 4 | navigation_model "github.com/eolinker/apinto-dashboard/modules/navigation/navigation-model" 5 | ) 6 | 7 | type INavigationService interface { 8 | Info(uuid string) (*navigation_model.Navigation, bool) 9 | List() []*navigation_model.Navigation 10 | } 11 | 12 | type INavigationDataService interface { 13 | GetNavigationData() []*navigation_model.Navigation 14 | } 15 | -------------------------------------------------------------------------------- /modules/notice/controller/routers.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | apinto_module "github.com/eolinker/apinto-dashboard/module" 5 | "net/http" 6 | ) 7 | 8 | func InitRouter() apinto_module.RoutersInfo { 9 | c := newNoticeController() 10 | return []apinto_module.RouterInfo{ 11 | { 12 | Method: http.MethodGet, 13 | Path: "/api/channels", 14 | Handler: "notice.getChannelsEnum", 15 | HandlerFunc: []apinto_module.HandlerFunc{c.channels}, 16 | }, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /modules/notice/driver.go: -------------------------------------------------------------------------------- 1 | package notice 2 | 3 | import "github.com/eolinker/apinto-dashboard/driver" 4 | 5 | type INoticeChannelDriverManager interface { 6 | driver.IDriverManager[IDriverNoticeChannel] 7 | } 8 | -------------------------------------------------------------------------------- /modules/notice/dto/notice.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type NoticeChannel struct { 4 | Uuid string `json:"uuid"` 5 | Title string `json:"title"` 6 | Type int `json:"type"` //1邮箱 2webhook 7 | } 8 | -------------------------------------------------------------------------------- /modules/notice/notice-service/driver.go: -------------------------------------------------------------------------------- 1 | package notice_service 2 | 3 | import ( 4 | driver_manager "github.com/eolinker/apinto-dashboard/driver" 5 | "github.com/eolinker/apinto-dashboard/modules/notice" 6 | ) 7 | 8 | type driverNoticeChannel struct { 9 | *driver_manager.DriverManager[notice.IDriverNoticeChannel] 10 | } 11 | 12 | func newNoticeChannelDriverManager() notice.INoticeChannelDriverManager { 13 | return &driverNoticeChannel{DriverManager: driver_manager.CreateDriverManager[notice.IDriverNoticeChannel]()} 14 | } 15 | 16 | // NewNoticeChannelDriverManager 17 | // todo mock 这个文件会报错 Loading input failed: don't know how to mock method of type *ast.IndexExpr 可能是泛型不支持 18 | // 单独提供个方法处理 19 | func NewNoticeChannelDriverManager() notice.INoticeChannelDriverManager { 20 | return &driverNoticeChannel{DriverManager: driver_manager.CreateDriverManager[notice.IDriverNoticeChannel]()} 21 | } 22 | -------------------------------------------------------------------------------- /modules/notice/notice-service/init.go: -------------------------------------------------------------------------------- 1 | package notice_service 2 | 3 | import "github.com/eolinker/eosc/common/bean" 4 | 5 | func init() { 6 | iNoticeChannelService := newNoticeChannelService() 7 | noticeChannelDriverManager := newNoticeChannelDriverManager() 8 | bean.Injection(&iNoticeChannelService) 9 | bean.Injection(¬iceChannelDriverManager) 10 | } 11 | -------------------------------------------------------------------------------- /modules/notice/notice-store/init.go: -------------------------------------------------------------------------------- 1 | package notice_store 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/store" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func init() { 9 | store.RegisterStore(func(db store.IDB) { 10 | iNoticeChannelStore := newNoticeChannelStore(db) 11 | iNoticeChannelStatStore := newNoticeChannelStatStore(db) 12 | iNoticeChannelVersionStore := newNoticeChannelVersionStore(db) 13 | bean.Injection(&iNoticeChannelStore) 14 | bean.Injection(&iNoticeChannelStatStore) 15 | bean.Injection(&iNoticeChannelVersionStore) 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /modules/notice/notice.go: -------------------------------------------------------------------------------- 1 | package notice 2 | 3 | import ( 4 | "context" 5 | "github.com/eolinker/apinto-dashboard/modules/notice/notice-model" 6 | ) 7 | 8 | type INoticeChannelService interface { 9 | CreateNoticeChannel(ctx context.Context, namespaceId, userID int, channel *notice_model.NoticeChannel) error 10 | UpdateNoticeChannel(ctx context.Context, namespaceId, userID int, channel *notice_model.NoticeChannel) error 11 | DeleteNoticeChannel(ctx context.Context, namespaceId, userID int, name string) error 12 | NoticeChannelList(ctx context.Context, namespaceId, typ_ int) ([]*notice_model.NoticeChannel, error) 13 | NoticeChannelByName(ctx context.Context, namespaceId int, name string) (*notice_model.NoticeChannel, error) 14 | InitChannelDriver() error 15 | } 16 | 17 | type IDriverNoticeChannel interface { 18 | SendTo(sends []string, title, msg string) error 19 | } 20 | -------------------------------------------------------------------------------- /modules/online/online-dto/common_online.go: -------------------------------------------------------------------------------- 1 | package online_dto 2 | 3 | import "github.com/eolinker/apinto-dashboard/enum" 4 | 5 | type OnlineOut struct { 6 | Name string `json:"name"` 7 | Status enum.OnlineStatus `json:"status"` 8 | Env string `json:"env"` 9 | Disable bool `json:"disable"` 10 | Operator string `json:"operator"` 11 | UpdateTime string `json:"update_time"` 12 | } 13 | 14 | type UpdateOnlineStatusInput struct { 15 | ClusterNames []string `json:"cluster_names"` 16 | } 17 | -------------------------------------------------------------------------------- /modules/online/service.go: -------------------------------------------------------------------------------- 1 | package online 2 | -------------------------------------------------------------------------------- /modules/openapi/open-api-controller/routers.go: -------------------------------------------------------------------------------- 1 | package open_api_controller 2 | 3 | import ( 4 | apinto_module "github.com/eolinker/apinto-dashboard/module" 5 | "net/http" 6 | ) 7 | 8 | func initRouter(name string) apinto_module.RoutersInfo { 9 | c := newOpenApiController() 10 | return apinto_module.RoutersInfo{ 11 | { 12 | Method: http.MethodGet, 13 | Path: "/api2/apis/import", 14 | Handler: "applications.getImportInfo", 15 | HandlerFunc: []apinto_module.HandlerFunc{c.getImportInfo}, 16 | Labels: apinto_module.RouterLabelOpenApi, 17 | }, 18 | { 19 | Method: http.MethodPost, 20 | Path: "/api2/apis/import", 21 | Handler: "applications.syncAPI", 22 | HandlerFunc: []apinto_module.HandlerFunc{c.syncAPI}, 23 | Labels: apinto_module.RouterLabelOpenApi, 24 | }, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /modules/openapi/openapi-dto/api_openAPI.go: -------------------------------------------------------------------------------- 1 | package openapi_dto 2 | 3 | type SyncImportData struct { 4 | Format string `json:"format"` 5 | Content []byte `json:"content"` 6 | ServiceName string `json:"upstream"` 7 | Server *ImportServerInfo `json:"server,omitempty"` 8 | GroupUUID string `json:"group"` 9 | Label string `json:"label"` 10 | Prefix string `json:"prefix"` 11 | } 12 | 13 | type ImportServerInfo struct { 14 | Scheme string `json:"scheme"` 15 | Nodes []*ImportNodesInfo `json:"nodes"` 16 | } 17 | 18 | type ImportNodesInfo struct { 19 | Url string `json:"url"` 20 | Weight int `json:"weight"` 21 | } 22 | -------------------------------------------------------------------------------- /modules/openapi/openapi-model/api_openAPI.go: -------------------------------------------------------------------------------- 1 | package openapi_model 2 | 3 | type ApiOpenAPIGroups struct { 4 | Uuid string `json:"uuid"` 5 | Name string `json:"name"` 6 | Children []*ApiOpenAPIGroups `json:"children,omitempty"` 7 | } 8 | 9 | type ApiOpenAPIService struct { 10 | Name string `json:"name"` 11 | Desc string `json:"desc"` 12 | Title string `json:"title"` 13 | } 14 | 15 | type ServiceStaticDriverConf struct { 16 | UseVariable bool `json:"use_variable"` 17 | AddrsVariable string `json:"addrs_variable,omitempty"` 18 | StaticConf []*ServiceStaticConf `json:"static_conf,omitempty"` 19 | } 20 | 21 | type ServiceStaticConf struct { 22 | Addr string `json:"addr"` 23 | Weight int `json:"weight"` 24 | } 25 | -------------------------------------------------------------------------------- /modules/openapi/openapi-service/init.go: -------------------------------------------------------------------------------- 1 | package openapi_service 2 | 3 | import "github.com/eolinker/eosc/common/bean" 4 | 5 | func init() { 6 | apiOpenAPI := newAPIOpenAPIService() 7 | //openAPI 8 | bean.Injection(&apiOpenAPI) 9 | } 10 | -------------------------------------------------------------------------------- /modules/openapp/open-app-dto/external_app.go: -------------------------------------------------------------------------------- 1 | package open_app_dto 2 | 3 | type ExternalAppInfoInput struct { 4 | Name string `json:"name"` 5 | Id string `json:"id"` 6 | Desc string `json:"desc"` 7 | } 8 | 9 | type ExternalAppInfoOutput struct { 10 | Name string `json:"name"` 11 | Id string `json:"id"` 12 | Desc string `json:"desc"` 13 | } 14 | -------------------------------------------------------------------------------- /modules/openapp/open-app-model/external-app.go: -------------------------------------------------------------------------------- 1 | package open_app_model 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/openapp/open-app-entry" 5 | ) 6 | 7 | type ExternalAppInfo struct { 8 | *open_app_entry.ExternalApplication 9 | } 10 | 11 | type ExtAppListItem struct { 12 | Id string `json:"id"` 13 | Name string `json:"name"` 14 | Token string `json:"token"` 15 | Tags string `json:"tags"` 16 | Status int `json:"status"` 17 | Operator string `json:"operator"` 18 | UpdateTime string `json:"update_time"` 19 | } 20 | -------------------------------------------------------------------------------- /modules/openapp/openapp-service/api_import_format.go: -------------------------------------------------------------------------------- 1 | package openapp_service 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/driver" 5 | "github.com/eolinker/apinto-dashboard/modules/openapi" 6 | ) 7 | 8 | const ( 9 | openAPI3 = "OpenAPI3.0" 10 | swagger2 = "Swagger2.0" 11 | ) 12 | 13 | type apiSyncFormatDriver struct { 14 | *driver.DriverManager[openapi.IAPISyncFormatDriver] 15 | } 16 | 17 | func (a *apiSyncFormatDriver) List() []string { 18 | return []string{swagger2, openAPI3} 19 | } 20 | 21 | func newAPISyncFormatManager() openapi.IAPISyncFormatManager { 22 | return &apiSyncFormatDriver{DriverManager: driver.CreateDriverManager[openapi.IAPISyncFormatDriver]()} 23 | } 24 | -------------------------------------------------------------------------------- /modules/openapp/openapp-service/init.go: -------------------------------------------------------------------------------- 1 | package openapp_service 2 | 3 | import ( 4 | driver2 "github.com/eolinker/apinto-dashboard/modules/openapi/driver" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func init() { 9 | //同步api文档格式管理器 10 | apiSyncFormatManager := newAPISyncFormatManager() 11 | openAPI3Driver := driver2.CreateOpenAPI3(openAPI3) 12 | openAPI2Driver := driver2.CreateOpenAPI2(swagger2) 13 | apiSyncFormatManager.RegisterDriver(openAPI3, openAPI3Driver) 14 | apiSyncFormatManager.RegisterDriver(swagger2, openAPI2Driver) 15 | bean.Injection(&apiSyncFormatManager) 16 | 17 | externalAPP := newExternalApplicationService() 18 | 19 | bean.Injection(&externalAPP) 20 | } 21 | -------------------------------------------------------------------------------- /modules/openapp/openapp-store/init.go: -------------------------------------------------------------------------------- 1 | package openapp_store 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/store" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func init() { 9 | store.RegisterStore(func(db store.IDB) { 10 | externalAPP := newExternalApplicationStore(db) 11 | bean.Injection(&externalAPP) 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /modules/plugin/plugin-entry/cluster_plugin_history.go: -------------------------------------------------------------------------------- 1 | package plugin_entry 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/base/history-entry" 5 | "time" 6 | ) 7 | 8 | // ClusterPluginHistory 集群绑定的插件变更记录表 9 | type ClusterPluginHistory struct { 10 | Id int 11 | NamespaceId int 12 | ClusterPluginID int 13 | OldValue ClusterPluginHistoryValue 14 | NewValue ClusterPluginHistoryValue 15 | OptType history_entry.OptType 16 | Operator int 17 | OptTime time.Time 18 | } 19 | 20 | type ClusterPluginHistoryValue struct { 21 | PluginName string `json:"plugin_name"` 22 | Status int `json:"status"` 23 | Config string `json:"config"` 24 | } 25 | -------------------------------------------------------------------------------- /modules/plugin/plugin-entry/cluster_plugin_runtime.go: -------------------------------------------------------------------------------- 1 | package plugin_entry 2 | 3 | import "time" 4 | 5 | // ClusterPluginRuntime 集群当前插件配置的版本 6 | type ClusterPluginRuntime struct { 7 | Id int `json:"id"` 8 | ClusterId int `json:"cluster_id"` 9 | NamespaceId int `json:"namespace_id"` 10 | VersionId int `json:"version_id"` 11 | IsOnline bool `json:"is_online"` 12 | Operator int `json:"operator"` 13 | CreateTime time.Time `json:"create_time"` 14 | UpdateTime time.Time `json:"update_time"` 15 | } 16 | -------------------------------------------------------------------------------- /modules/plugin/plugin-entry/plugin_history.go: -------------------------------------------------------------------------------- 1 | package plugin_entry 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/base/history-entry" 5 | "time" 6 | ) 7 | 8 | type PluginHistory struct { 9 | Id int 10 | PluginID int 11 | NamespaceId int 12 | OldValue PluginHistoryInfo 13 | NewValue PluginHistoryInfo 14 | OptType history_entry.OptType //1新增 2修改 3删除 15 | OptTime time.Time 16 | Operator int 17 | } 18 | 19 | type PluginHistoryInfo struct { 20 | Plugin Plugin `json:"plugin"` 21 | } 22 | -------------------------------------------------------------------------------- /modules/plugin/plugin-service/extender_cache.go: -------------------------------------------------------------------------------- 1 | package plugin_service 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/cache" 5 | "github.com/eolinker/apinto-dashboard/modules/plugin/plugin-model" 6 | "time" 7 | ) 8 | 9 | type IExtenderCache interface { 10 | cache.IRedisCacheNoKey[plugin_model.ExtenderInfo] 11 | } 12 | 13 | func newIExtenderCache() IExtenderCache { 14 | return cache.CreateRedisCacheNoKey[plugin_model.ExtenderInfo](time.Minute*5, "extender") 15 | 16 | } 17 | -------------------------------------------------------------------------------- /modules/plugin/plugin-service/init.go: -------------------------------------------------------------------------------- 1 | package plugin_service 2 | 3 | import ( 4 | "github.com/eolinker/eosc/common/bean" 5 | ) 6 | 7 | func init() { 8 | pluginServiceInfo := newPluginService() 9 | clusterPluginServiceInfo := newClusterPluginService() 10 | bean.Injection(&pluginServiceInfo) 11 | bean.Injection(&clusterPluginServiceInfo) 12 | iExtenderCache := newIExtenderCache() 13 | bean.Injection(&iExtenderCache) 14 | 15 | } 16 | -------------------------------------------------------------------------------- /modules/plugin/plugin_timer/init.go: -------------------------------------------------------------------------------- 1 | package plugin_timer 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | func ExtenderTimer() { 8 | 9 | iExtender := newExtender() 10 | 11 | //第一次启动就去更新扩展ID插件 12 | go iExtender.UpdateExtender() 13 | secondTick := time.Tick(time.Second) 14 | for t := range secondTick { 15 | if t.Second() == 0 { //1分钟执行一次 16 | go iExtender.UpdateExtender() 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /modules/plugin_template/plugin-template-entry/plugin_template_history.go: -------------------------------------------------------------------------------- 1 | package plugin_template_entry 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/base/history-entry" 5 | "time" 6 | ) 7 | 8 | type PluginTemplateHistory struct { 9 | Id int 10 | PluginTemplateID int 11 | NamespaceId int 12 | OldValue PluginTemplateHistoryInfo 13 | NewValue PluginTemplateHistoryInfo 14 | OptType history_entry.OptType //1新增 2修改 3删除 15 | OptTime time.Time 16 | Operator int 17 | } 18 | 19 | type PluginTemplateHistoryInfo struct { 20 | PluginTemplate PluginTemplate `json:"plugin_template"` 21 | Config PluginTemplateVersionConfig `json:"config"` 22 | } 23 | -------------------------------------------------------------------------------- /modules/plugin_template/plugin-template-entry/plugin_template_runtime.go: -------------------------------------------------------------------------------- 1 | package plugin_template_entry 2 | 3 | import "time" 4 | 5 | type PluginTemplateRuntime struct { 6 | Id int 7 | NamespaceId int 8 | PluginTemplateID int 9 | ClusterID int 10 | VersionID int 11 | IsOnline bool 12 | Disable bool 13 | Operator int 14 | CreateTime time.Time 15 | UpdateTime time.Time 16 | } 17 | -------------------------------------------------------------------------------- /modules/plugin_template/plugin-template-entry/plugin_template_stat.go: -------------------------------------------------------------------------------- 1 | package plugin_template_entry 2 | 3 | type PluginTemplateStat struct { 4 | PluginTemplateId int 5 | VersionID int 6 | } 7 | -------------------------------------------------------------------------------- /modules/plugin_template/plugin-template-entry/plugin_template_version.go: -------------------------------------------------------------------------------- 1 | package plugin_template_entry 2 | 3 | import "time" 4 | 5 | type PluginTemplateVersion struct { 6 | Id int 7 | PluginTemplateId int 8 | NamespaceID int 9 | PluginTemplateVersionConfig 10 | Operator int 11 | CreateTime time.Time 12 | } 13 | 14 | func (p *PluginTemplateVersion) SetVersionId(id int) { 15 | p.Id = id 16 | } 17 | 18 | type PluginTemplateVersionConfig struct { 19 | Plugins []*PluginTemplateVersionConfigDetail `json:"plugins"` 20 | } 21 | 22 | type PluginTemplateVersionConfigDetail struct { 23 | UUID string `json:"uuid,omitempty"` 24 | Name string `json:"name,omitempty"` 25 | Config string `json:"config,omitempty"` 26 | Disable bool `json:"disable,omitempty"` 27 | } 28 | -------------------------------------------------------------------------------- /modules/plugin_template/plugin-template-entry/publish_history.go: -------------------------------------------------------------------------------- 1 | package plugin_template_entry 2 | 3 | import "time" 4 | 5 | type PluginTemplatePublishHistory struct { 6 | Id int 7 | VersionName string 8 | ClusterId int 9 | NamespaceId int 10 | Desc string 11 | VersionId int 12 | Target int 13 | PluginTemplateVersionConfig 14 | OptType int 15 | Operator int 16 | OptTime time.Time 17 | } 18 | -------------------------------------------------------------------------------- /modules/plugin_template/plugin-template-service/init.go: -------------------------------------------------------------------------------- 1 | package plugin_template_service 2 | 3 | import ( 4 | "github.com/eolinker/eosc/common/bean" 5 | ) 6 | 7 | func init() { 8 | 9 | clusterTemplatePlugin := newPluginTemplateService() 10 | 11 | bean.Injection(&clusterTemplatePlugin) 12 | } 13 | -------------------------------------------------------------------------------- /modules/plugin_template/plugin-template-store/init.go: -------------------------------------------------------------------------------- 1 | package plugin_template_store 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/store" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func init() { 9 | store.RegisterStore(func(db store.IDB) { 10 | historyStore := newPluginTemplateHistoryStore(db) 11 | templateStore := newPluginTemplateStore(db) 12 | statStore := newPluginTemplateStatStore(db) 13 | versionStore := newPluginTemplateVersionStore(db) 14 | publishHistory := newPluginTemplatePublishHistoryStore(db) 15 | 16 | bean.Injection(&historyStore) 17 | bean.Injection(&templateStore) 18 | bean.Injection(&statStore) 19 | bean.Injection(&versionStore) 20 | bean.Injection(&publishHistory) 21 | }) 22 | } 23 | -------------------------------------------------------------------------------- /modules/random/random-service/init.go: -------------------------------------------------------------------------------- 1 | package random_service 2 | 3 | import "github.com/eolinker/eosc/common/bean" 4 | 5 | func init() { 6 | random := newRandomService() 7 | 8 | bean.Injection(&random) 9 | } 10 | -------------------------------------------------------------------------------- /modules/random/random-service/random.go: -------------------------------------------------------------------------------- 1 | package random_service 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/common" 5 | "github.com/eolinker/apinto-dashboard/modules/random" 6 | ) 7 | 8 | type randomService struct { 9 | } 10 | 11 | func newRandomService() random.IRandomService { 12 | return &randomService{} 13 | } 14 | 15 | func (randomService) RandomStr(ruleName string) string { 16 | // todo 这里需要换成通过注册取代来实现 17 | switch ruleName { 18 | case "application": 19 | return common.RandStr(16) 20 | case "external-app": 21 | return common.RandStr(16) 22 | case "external-app-token": //外部应用长度32的token 23 | return common.RandStr(32) 24 | case "password": 25 | return "12345678" 26 | return common.RandStr(8) 27 | default: 28 | return "" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /modules/random/random.go: -------------------------------------------------------------------------------- 1 | package random 2 | 3 | type IRandomService interface { 4 | RandomStr(ruleName string) string 5 | } 6 | -------------------------------------------------------------------------------- /modules/remote_storage/entry/remote_key_object.go: -------------------------------------------------------------------------------- 1 | package entry 2 | 3 | import "gorm.io/gorm" 4 | 5 | type RemoteKeyObject struct { 6 | Module string `gorm:"uniqueIndex:module_key;index;not null;size:255;column:module;comment:模块名"` 7 | Key string `gorm:"uniqueIndex:module_key;not null;size:32;column:key"` //TODO key要多长 8 | Object interface{} `gorm:"type:text;serializer:json;column:object"` 9 | gorm.Model 10 | } 11 | 12 | func (c *RemoteKeyObject) TableName() string { 13 | return "remote_storage" 14 | } 15 | 16 | func (c *RemoteKeyObject) IdValue() int { 17 | return int(c.ID) 18 | } 19 | -------------------------------------------------------------------------------- /modules/remote_storage/model/remote_storage.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import "time" 4 | 5 | type RemoteStorage struct { 6 | Module string 7 | Key string 8 | Object interface{} 9 | UpdateAt time.Time 10 | CreateAt time.Time 11 | } 12 | -------------------------------------------------------------------------------- /modules/remote_storage/remote_storage.go: -------------------------------------------------------------------------------- 1 | package remote_storage 2 | 3 | import "github.com/eolinker/apinto-dashboard/modules/remote_storage/model" 4 | 5 | type IRemoteStorageService interface { 6 | Get(module, key string) (*model.RemoteStorage, error) 7 | Save(module, key string, object interface{}) error 8 | } 9 | -------------------------------------------------------------------------------- /modules/remote_storage/service/init.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import "github.com/eolinker/eosc/common/bean" 4 | 5 | func init() { 6 | remoteStorage := newRemoteStorageService() 7 | bean.Injection(&remoteStorage) 8 | 9 | } 10 | -------------------------------------------------------------------------------- /modules/remote_storage/store/init.go: -------------------------------------------------------------------------------- 1 | package store 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/store" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func init() { 9 | store.RegisterStore(func(db store.IDB) { 10 | remoteStorageStore := newRemoteStorageStore(db) 11 | bean.Injection(&remoteStorageStore) 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /modules/strategy/config/content-type.yml: -------------------------------------------------------------------------------- 1 | - 2 | content_type: application/json 3 | body: |- 4 | { 5 | "msg":"很抱歉,$api 暂停服务,请稍候再试!" 6 | } 7 | - 8 | content_type: application/xml 9 | body: |- 10 | 11 | 很抱歉,$api 暂停服务,请稍候再试! 12 | - 13 | content_type: text/html 14 | body: "

很抱歉,$api 暂停服务,请稍候再试!

" -------------------------------------------------------------------------------- /modules/strategy/strategy-controller/stragety-traffic.go: -------------------------------------------------------------------------------- 1 | package strategy_controller 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/strategy/config" 5 | strategy_entry "github.com/eolinker/apinto-dashboard/modules/strategy/strategy-entry" 6 | "github.com/eolinker/apinto-dashboard/modules/strategy/strategy-service" 7 | "github.com/eolinker/apinto-dashboard/modules/strategy/strategy-service/strategy-handler" 8 | ) 9 | 10 | func newStrategyTrafficController() *strategyController[strategy_entry.StrategyTrafficLimitConfig, strategy_entry.StrategyTrafficLimitConfig] { 11 | strategyService := strategy_service.NewStrategyService(strategy_handler.NewStrategyTrafficHandler("strategy-limiting"), config.StrategyTrafficRuntimeKind) 12 | 13 | c := newStrategyController(strategyService) 14 | 15 | return c 16 | } 17 | -------------------------------------------------------------------------------- /modules/strategy/strategy-controller/strategy-cache.go: -------------------------------------------------------------------------------- 1 | package strategy_controller 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/strategy/config" 5 | strategy_entry "github.com/eolinker/apinto-dashboard/modules/strategy/strategy-entry" 6 | "github.com/eolinker/apinto-dashboard/modules/strategy/strategy-service" 7 | "github.com/eolinker/apinto-dashboard/modules/strategy/strategy-service/strategy-handler" 8 | ) 9 | 10 | func newStrategyCacheController() *strategyController[strategy_entry.StrategyCacheConfig, strategy_entry.StrategyCacheConfig] { 11 | strategyService := strategy_service.NewStrategyService(strategy_handler.NewStrategyCacheHandler("strategy-cache"), config.StrategyCacheRuntimeKind) 12 | 13 | c := newStrategyController(strategyService) 14 | return c 15 | } 16 | -------------------------------------------------------------------------------- /modules/strategy/strategy-controller/strategy-fuse.go: -------------------------------------------------------------------------------- 1 | package strategy_controller 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/strategy/config" 5 | strategy_entry "github.com/eolinker/apinto-dashboard/modules/strategy/strategy-entry" 6 | "github.com/eolinker/apinto-dashboard/modules/strategy/strategy-service" 7 | "github.com/eolinker/apinto-dashboard/modules/strategy/strategy-service/strategy-handler" 8 | ) 9 | 10 | func newStrategyFuseController() *strategyController[strategy_entry.StrategyFuseConfig, strategy_entry.StrategyFuseConfig] { 11 | strategyService := strategy_service.NewStrategyService(strategy_handler.NewStrategyFuseHandler("strategy-fuse"), config.StrategyFuseRuntimeKind) 12 | 13 | c := newStrategyController(strategyService) 14 | return c 15 | } 16 | -------------------------------------------------------------------------------- /modules/strategy/strategy-controller/strategy-grey.go: -------------------------------------------------------------------------------- 1 | package strategy_controller 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/strategy/config" 5 | strategy_entry "github.com/eolinker/apinto-dashboard/modules/strategy/strategy-entry" 6 | "github.com/eolinker/apinto-dashboard/modules/strategy/strategy-service" 7 | "github.com/eolinker/apinto-dashboard/modules/strategy/strategy-service/strategy-handler" 8 | ) 9 | 10 | func newStrategyGreyController() *strategyController[strategy_entry.StrategyGreyConfig, strategy_entry.StrategyGreyConfig] { 11 | strategyService := strategy_service.NewStrategyService(strategy_handler.NewStrategyGreyHandler("strategy-grey"), config.StrategyGreyRuntimeKind) 12 | 13 | c := newStrategyController(strategyService) 14 | return c 15 | } 16 | -------------------------------------------------------------------------------- /modules/strategy/strategy-controller/strategy-visit.go: -------------------------------------------------------------------------------- 1 | package strategy_controller 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/strategy/config" 5 | strategy_entry "github.com/eolinker/apinto-dashboard/modules/strategy/strategy-entry" 6 | strategy_model "github.com/eolinker/apinto-dashboard/modules/strategy/strategy-model" 7 | "github.com/eolinker/apinto-dashboard/modules/strategy/strategy-service" 8 | "github.com/eolinker/apinto-dashboard/modules/strategy/strategy-service/strategy-handler" 9 | ) 10 | 11 | func newStrategyVisitController() *strategyController[strategy_entry.StrategyVisitConfig, strategy_model.VisitInfoOutputConf] { 12 | strategyService := strategy_service.NewStrategyService(strategy_handler.NewStrategyVisitHandler("strategy-visit"), config.StrategyVisitRuntimeKind) 13 | 14 | c := newStrategyController(strategyService) 15 | return c 16 | } 17 | -------------------------------------------------------------------------------- /modules/strategy/strategy-entry/strategy_history.go: -------------------------------------------------------------------------------- 1 | package strategy_entry 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/base/history-entry" 5 | "time" 6 | ) 7 | 8 | type StrategyHistoryInfo struct { 9 | Strategy Strategy `json:"strategy,omitempty"` 10 | Config StrategyConfigInfo `json:"config"` 11 | } 12 | 13 | type StrategyHistory struct { 14 | Id int 15 | StrategyId int 16 | NamespaceId int 17 | OldValue StrategyHistoryInfo 18 | NewValue StrategyHistoryInfo 19 | OptType history_entry.OptType //1新增 2修改 3删除 20 | OptTime time.Time 21 | Operator int 22 | } 23 | -------------------------------------------------------------------------------- /modules/strategy/strategy-entry/strategy_publish_history.go: -------------------------------------------------------------------------------- 1 | package strategy_entry 2 | 3 | import "time" 4 | 5 | type StrategyPublishHistory struct { 6 | Id int 7 | VersionName string 8 | ClusterId int 9 | NamespaceId int 10 | Desc string 11 | VersionId int 12 | Publish []*StrategyPublishConfigInfo //此次发布的数据 13 | OptType int 14 | Operator int 15 | CreateTime time.Time 16 | } 17 | 18 | //type StrategyPublishHistoryInfo struct { 19 | // Publish []*StrategyPublishConfigInfo `json:"publish"` 20 | //} 21 | -------------------------------------------------------------------------------- /modules/strategy/strategy-entry/strategy_runtime.go: -------------------------------------------------------------------------------- 1 | package strategy_entry 2 | 3 | import "time" 4 | 5 | type StrategyRuntime struct { 6 | Id int `json:"id"` 7 | ClusterId int `json:"cluster_id"` 8 | NamespaceId int `json:"namespace_id"` 9 | VersionId int `json:"version_id"` 10 | IsOnline bool `json:"is_online"` 11 | Operator int `json:"operator"` 12 | CreateTime time.Time `json:"create_time"` 13 | UpdateTime time.Time `json:"update_time"` 14 | } 15 | -------------------------------------------------------------------------------- /modules/strategy/strategy-entry/strategy_stat.go: -------------------------------------------------------------------------------- 1 | package strategy_entry 2 | 3 | type StrategyStat struct { 4 | StrategyId int 5 | VersionId int 6 | } 7 | -------------------------------------------------------------------------------- /modules/strategy/strategy-service/filters.go: -------------------------------------------------------------------------------- 1 | package strategy_service 2 | 3 | type IFilterHandler interface { 4 | } 5 | -------------------------------------------------------------------------------- /modules/strategy/strategy-service/init.go: -------------------------------------------------------------------------------- 1 | package strategy_service 2 | 3 | import "github.com/eolinker/eosc/common/bean" 4 | 5 | func init() { 6 | commonStrategy := newStrategyCommonService() 7 | 8 | bean.Injection(&commonStrategy) 9 | } 10 | -------------------------------------------------------------------------------- /modules/strategy/strategy-store/init.go: -------------------------------------------------------------------------------- 1 | package strategy_store 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/store" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func init() { 9 | store.RegisterStore(func(db store.IDB) { 10 | strategy := newStrategyStore(db) 11 | strategyStat := newStrategyStatStore(db) 12 | 13 | strategyVersion := newStrategyVersionStore(db) 14 | 15 | strategyHistory := newStrategyHistoryStore(db) 16 | bean.Injection(&strategy) 17 | bean.Injection(&strategyStat) 18 | 19 | bean.Injection(&strategyVersion) 20 | 21 | bean.Injection(&strategyHistory) 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /modules/system/service/init.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package service 10 | 11 | import ( 12 | "github.com/eolinker/eosc/common/bean" 13 | ) 14 | 15 | func init() { 16 | 17 | iml := newDataServiceIml() 18 | bean.Injection(&iml) 19 | } 20 | -------------------------------------------------------------------------------- /modules/system/system-entry/system_info.go: -------------------------------------------------------------------------------- 1 | package system_entry 2 | 3 | // SystemInfo 系统信息表 4 | type SystemInfo struct { 5 | Id int `gorm:"type:int(11);size:11;not null;auto_increment;primary_key;column:id;comment:主键ID"` 6 | Key string `gorm:"size:20;not null;column:key;uniqueIndex:unique_key;comment:健"` 7 | Value []byte `gorm:"type:text;not null;column:value;comment:值"` 8 | } 9 | 10 | func (*SystemInfo) TableName() string { 11 | return "system_info" 12 | } 13 | 14 | func (c *SystemInfo) IdValue() int { 15 | return c.Id 16 | } 17 | -------------------------------------------------------------------------------- /modules/system/system-store/init.go: -------------------------------------------------------------------------------- 1 | package system_store 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/store" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func init() { 9 | store.RegisterStore(func(db store.IDB) { 10 | systemInfo := newSystemInfoStore(db) 11 | bean.Injection(&systemInfo) 12 | 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /modules/system/system.go: -------------------------------------------------------------------------------- 1 | package system 2 | 3 | type ISystemConfigService[T any] interface { 4 | Get() (*T, error) 5 | Set(t *T) error 6 | } 7 | type ISystemConfigServiceSimple interface { 8 | Get() ([]byte, error) 9 | Set(v []byte) error 10 | } 11 | type ISystemConfigDataService interface { 12 | Get(key string) ([]byte, error) 13 | Set(key string, v []byte) error 14 | } 15 | -------------------------------------------------------------------------------- /modules/user/user-dto/access.go: -------------------------------------------------------------------------------- 1 | package user_dto 2 | 3 | type UserAccess struct { 4 | Name string `json:"name"` 5 | Access string `json:"access"` 6 | } 7 | -------------------------------------------------------------------------------- /modules/user/user-model/session.go: -------------------------------------------------------------------------------- 1 | package user_model 2 | 3 | type Session struct { 4 | Jwt string 5 | RJwt string 6 | } 7 | -------------------------------------------------------------------------------- /modules/user/user-service/init.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "github.com/eolinker/eosc/common/bean" 5 | ) 6 | 7 | func init() { 8 | infoService := newUserInfoService() 9 | bean.Injection(&infoService) 10 | userInfo := newUserInfoIdCache() 11 | userNameInfo := newUserInfoNameCache() 12 | session := newSessionCache() 13 | bean.Injection(&userInfo) 14 | bean.Injection(&userNameInfo) 15 | bean.Injection(&session) 16 | 17 | } 18 | -------------------------------------------------------------------------------- /modules/user/user-service/session.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/eolinker/apinto-dashboard/modules/user" 8 | user_model "github.com/eolinker/apinto-dashboard/modules/user/user-model" 9 | 10 | "github.com/eolinker/apinto-dashboard/cache" 11 | ) 12 | 13 | func sessionCacheKey(session string) string { 14 | return fmt.Sprintf("session:%s", session) 15 | } 16 | 17 | func newSessionCache() user.ISessionCache { 18 | return cache.CreateRedisCache[user_model.Session](time.Hour*24*7, sessionCacheKey, "apinto", "session") 19 | 20 | } 21 | -------------------------------------------------------------------------------- /modules/user/user-store/init.go: -------------------------------------------------------------------------------- 1 | package user_store 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/store" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func init() { 9 | store.RegisterStore(func(db store.IDB) { 10 | userInfo := newUserInfoStore(db) 11 | 12 | bean.Injection(&userInfo) 13 | 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /modules/variable/variable-dto/global_variable.go: -------------------------------------------------------------------------------- 1 | package variable_dto 2 | 3 | import "github.com/eolinker/apinto-dashboard/enum" 4 | 5 | type GlobalVariableListItem struct { 6 | Key string `json:"key"` 7 | Status enum.VariableUsageStatus `json:"status"` 8 | Description string `json:"description"` 9 | Operator string `json:"operator"` 10 | CreateTime string `json:"create_time"` 11 | } 12 | 13 | type GlobalVariableDetailsItem struct { 14 | ClusterName string `json:"cluster_name"` 15 | Environment string `json:"environment"` 16 | Value string `json:"value"` 17 | Status enum.PublishType `json:"publish_status"` 18 | } 19 | 20 | type GlobalVariableInput struct { 21 | Key string `json:"key"` 22 | Desc string `json:"desc"` 23 | } 24 | -------------------------------------------------------------------------------- /modules/variable/variable-entry/variable_history.go: -------------------------------------------------------------------------------- 1 | package variable_entry 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/base/history-entry" 5 | "time" 6 | ) 7 | 8 | // VariableHistory 集群绑定的环境变量变更记录表 9 | type VariableHistory struct { 10 | Id int 11 | ClusterId int 12 | NamespaceId int 13 | VariableId int 14 | OldValue VariableValue 15 | NewValue VariableValue 16 | OptType history_entry.OptType 17 | Operator int 18 | OptTime time.Time 19 | } 20 | 21 | type VariableValue struct { 22 | Key string `json:"key,omitempty"` 23 | Value string `json:"value,omitempty"` 24 | } 25 | -------------------------------------------------------------------------------- /modules/variable/variable-entry/variable_publish_history.go: -------------------------------------------------------------------------------- 1 | package variable_entry 2 | 3 | import "time" 4 | 5 | type VariablePublishHistory struct { 6 | Id int 7 | VersionName string 8 | ClusterId int 9 | NamespaceId int 10 | Desc string 11 | VersionId int 12 | VariablePublishHistoryInfo 13 | OptType int 14 | Operator int 15 | OptTime time.Time 16 | } 17 | 18 | type VariablePublishHistoryInfo struct { 19 | VariableToPublish []*VariableToPublish `json:"variable_to_publish"` //发布记录 20 | } 21 | -------------------------------------------------------------------------------- /modules/variable/variable-entry/variable_runtime.go: -------------------------------------------------------------------------------- 1 | package variable_entry 2 | 3 | import "time" 4 | 5 | // VariableRuntime 集群当前版本 6 | type VariableRuntime struct { 7 | Id int `json:"id"` 8 | ClusterId int `json:"cluster_id"` 9 | NamespaceId int `json:"namespace_id"` 10 | VersionId int `json:"version_id"` 11 | IsOnline bool `json:"is_online"` 12 | Operator int `json:"operator"` 13 | CreateTime time.Time `json:"create_time"` 14 | UpdateTime time.Time `json:"update_time"` 15 | } 16 | -------------------------------------------------------------------------------- /modules/variable/variable-model/global_variable.go: -------------------------------------------------------------------------------- 1 | package variable_model 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/modules/variable/variable-entry" 5 | ) 6 | 7 | type GlobalVariable struct { 8 | *variable_entry.Variables 9 | } 10 | 11 | type GlobalVariableListItem struct { 12 | *variable_entry.Variables 13 | Status int 14 | OperatorStr string 15 | } 16 | 17 | type GlobalVariableDetails struct { 18 | *variable_entry.ClusterVariable 19 | Status int 20 | ClusterName string 21 | Environment string 22 | } 23 | -------------------------------------------------------------------------------- /modules/variable/variable-service/init.go: -------------------------------------------------------------------------------- 1 | package variable_service 2 | 3 | import "github.com/eolinker/eosc/common/bean" 4 | 5 | func init() { 6 | globalVariable := newGlobalVariableService() 7 | 8 | bean.Injection(&globalVariable) 9 | 10 | clusterVariable := newClusterVariableService() 11 | 12 | bean.Injection(&clusterVariable) 13 | } 14 | -------------------------------------------------------------------------------- /modules/variable/variable-store/init.go: -------------------------------------------------------------------------------- 1 | package variable_store 2 | 3 | import ( 4 | "github.com/eolinker/apinto-dashboard/store" 5 | "github.com/eolinker/eosc/common/bean" 6 | ) 7 | 8 | func init() { 9 | store.RegisterStore(func(db store.IDB) { 10 | globalVariable := newGlobalVariableStore(db) 11 | clusterVariable := newClusterVariableStore(db) 12 | 13 | variableHistory := newVariableHistoryStore(db) 14 | variablePublishVersion := newVariablePublishVersionStore(db) 15 | variableRuntime := newVariableRuntimeStore(db) 16 | variablePublishHistory := newVariablePublishHistoryStore(db) 17 | bean.Injection(&variableHistory) 18 | bean.Injection(&variablePublishVersion) 19 | bean.Injection(&variableRuntime) 20 | bean.Injection(&variablePublishHistory) 21 | bean.Injection(&clusterVariable) 22 | bean.Injection(&globalVariable) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /plugin/go-plugin/example/.gitignore: -------------------------------------------------------------------------------- 1 | /example 2 | /example.exe 3 | -------------------------------------------------------------------------------- /plugin/go-plugin/example/config.yml: -------------------------------------------------------------------------------- 1 | port: 8080 2 | mysql: 3 | user_name: "apinto" 4 | password: "Apinto123" 5 | ip: "47.106.231.246" 6 | port: 30006 7 | db: "apserver" 8 | redis: 9 | user_name: "" 10 | password: "I*IR1VGJ8tT5Y0)G" 11 | addr: 12 | - 172.18.166.219:7201 13 | - 172.18.166.219:7202 14 | - 172.18.166.219:7203 15 | - 172.18.166.219:7204 16 | - 172.18.166.219:7205 17 | - 172.18.166.219:7206 18 | error_log: 19 | dir: work/logs # 日志放置目录, 支持相对路径和绝对路径 20 | file_name: error.log # 错误日志文件名 21 | log_level: debug # 错误日志等级,可选:panic,fatal,error,warning,info,debug,trace 不填或者非法则为info 22 | log_expire: 7d # 错误日志过期时间,默认单位为天,d|天,h|小时, 不合法配置默认为7d 23 | log_period: day # 错误日志切割周期,仅支持day、hour 24 | -------------------------------------------------------------------------------- /plugin/go-plugin/example/plugin/.gitignore: -------------------------------------------------------------------------------- 1 | /plugin 2 | /plugin.exe 3 | -------------------------------------------------------------------------------- /plugin/go-plugin/plugin/config.go: -------------------------------------------------------------------------------- 1 | package plugin 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/eolinker/apinto-dashboard/config" 6 | "os" 7 | ) 8 | 9 | func init() { 10 | initConfig() 11 | initLogger() 12 | } 13 | func initConfig() { 14 | 15 | if os.Getenv("ApintoDashboardConfig") != "true" { 16 | config.ReadConfig() 17 | return 18 | } 19 | c := new(config.Config) 20 | err := json.NewDecoder(os.Stdin).Decode(c) 21 | if err != nil { 22 | logger.Error("read config", err) 23 | return 24 | } 25 | config.SetConfig(c) 26 | 27 | } 28 | -------------------------------------------------------------------------------- /plugin/go-plugin/plugin/response.go: -------------------------------------------------------------------------------- 1 | package plugin 2 | 3 | import ( 4 | "bytes" 5 | "net/http" 6 | ) 7 | 8 | type responseWriter struct { 9 | buf *bytes.Buffer 10 | header http.Header 11 | status int 12 | } 13 | 14 | func newResponseWriter() *responseWriter { 15 | return &responseWriter{ 16 | header: make(http.Header), 17 | buf: bytes.NewBuffer(nil), 18 | } 19 | } 20 | 21 | func (r *responseWriter) Header() http.Header { 22 | return r.header 23 | } 24 | 25 | func (r *responseWriter) Write(data []byte) (int, error) { 26 | return r.buf.Write(data) 27 | } 28 | 29 | func (r *responseWriter) WriteHeader(statusCode int) { 30 | r.status = statusCode 31 | } 32 | -------------------------------------------------------------------------------- /plugin/go-plugin/plugin/server_keys.go: -------------------------------------------------------------------------------- 1 | package plugin 2 | 3 | import ( 4 | "context" 5 | "github.com/gin-gonic/gin" 6 | "os" 7 | ) 8 | 9 | type ginKeysKey struct{} 10 | 11 | var ( 12 | GinKeys = &ginKeysKey{} 13 | ) 14 | 15 | func Engine() *gin.Engine { 16 | gin.SetMode(gin.ReleaseMode) 17 | engine := gin.New() 18 | engine.Use(gin.LoggerWithWriter(os.Stderr)) 19 | engine.Use(KeyForGin) 20 | engine.ContextWithFallback = true 21 | return engine 22 | } 23 | func widthKey(ctx context.Context, keys map[string]interface{}) context.Context { 24 | ctx = context.WithValue(ctx, GinKeys, keys) 25 | return ctx 26 | } 27 | func KeyForGin(ginCtx *gin.Context) { 28 | value := ginCtx.Value(GinKeys) 29 | if value != nil { 30 | keys := value.(map[string]interface{}) 31 | if keys == nil { 32 | return 33 | } 34 | for k, v := range keys { 35 | ginCtx.Set(k, v) 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /plugin/go-plugin/proto/gen.go: -------------------------------------------------------------------------------- 1 | //go:generate protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative plugin.proto 2 | 3 | package proto 4 | -------------------------------------------------------------------------------- /plugin/go-plugin/shared/config.go: -------------------------------------------------------------------------------- 1 | package shared 2 | 3 | import "github.com/hashicorp/go-plugin" 4 | 5 | var HandshakeConfig = plugin.HandshakeConfig{ 6 | ProtocolVersion: 1, 7 | MagicCookieKey: "HTTP_HANDLER_PLUGIN", 8 | MagicCookieValue: "Apinto_Dashboard_Plugin", 9 | } 10 | -------------------------------------------------------------------------------- /plugin/go-plugin/shared/handler.go: -------------------------------------------------------------------------------- 1 | package shared 2 | 3 | import ( 4 | module "github.com/eolinker/apinto-dashboard/module" 5 | "net/http" 6 | ) 7 | 8 | const PluginHandlerName = "apinto-dashboard" 9 | 10 | type HttpHandler interface { 11 | ServeHTTP(w http.ResponseWriter, r *http.Request) 12 | } 13 | 14 | type MiddlewareHandler interface { 15 | OnHttpRequest(r *module.MiddlewareRequest) module.MiddlewareResponseWriter 16 | onHttpResponse(r *module.MiddlewareRequest) module.MiddlewareResponseWriter 17 | } 18 | -------------------------------------------------------------------------------- /plugin/local/cmd_unix.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | package local 4 | 5 | import ( 6 | "path/filepath" 7 | ) 8 | 9 | var PluginDir, _ = filepath.Abs("local") 10 | 11 | func cmdPath(name string) string { 12 | return filepath.Join(PluginDir, name) 13 | } 14 | -------------------------------------------------------------------------------- /plugin/local/cmd_win.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package local 4 | 5 | import ( 6 | "fmt" 7 | "path/filepath" 8 | ) 9 | 10 | var PluginDir, _ = filepath.Abs("local") 11 | 12 | func cmdPath(name string) string { 13 | return filepath.Join(PluginDir, fmt.Sprintf("%s.exe", name)) 14 | } 15 | -------------------------------------------------------------------------------- /plugin/local/config.go: -------------------------------------------------------------------------------- 1 | package local 2 | 3 | type Config struct { 4 | //Server string `json:"server"` 5 | //Header map[string]string `json:"header"` 6 | //Query map[string]string `json:"query"` 7 | Initialize map[string]string `json:"initialize"` 8 | } 9 | -------------------------------------------------------------------------------- /plugin/local/driver.go: -------------------------------------------------------------------------------- 1 | package local 2 | 3 | import ( 4 | apinto_module "github.com/eolinker/apinto-dashboard/module" 5 | ) 6 | 7 | type tDriver struct { 8 | } 9 | 10 | func NewDriver() apinto_module.Driver { 11 | return &tDriver{} 12 | } 13 | 14 | func (d *tDriver) CreatePlugin(define interface{}) (apinto_module.Plugin, error) { 15 | return newTPlugin(define) 16 | } 17 | -------------------------------------------------------------------------------- /plugin/remote/config.go: -------------------------------------------------------------------------------- 1 | package remote 2 | 3 | type Config struct { 4 | Server string `json:"server"` 5 | Header map[string]string `json:"header"` 6 | Query map[string]string `json:"query"` 7 | Initialize map[string]string `json:"initialize"` 8 | } 9 | 10 | type DtoOpenModeParam struct { 11 | Name string `json:"name"` 12 | Value string `json:"value"` 13 | Type string `json:"type,omitempty"` 14 | } 15 | -------------------------------------------------------------------------------- /plugin/remote/driver.go: -------------------------------------------------------------------------------- 1 | package remote 2 | 3 | import ( 4 | apinto_module "github.com/eolinker/apinto-dashboard/module" 5 | ) 6 | 7 | type rDriver struct { 8 | } 9 | 10 | func NewDriver() apinto_module.Driver { 11 | return &rDriver{} 12 | } 13 | 14 | func (d *rDriver) CreatePlugin(define interface{}) (apinto_module.Plugin, error) { 15 | return newRPlugin(define) 16 | } 17 | -------------------------------------------------------------------------------- /plugin/remote/module.go: -------------------------------------------------------------------------------- 1 | package remote 2 | 3 | import ( 4 | apinto_module "github.com/eolinker/apinto-dashboard/module" 5 | ) 6 | 7 | type rModule struct { 8 | name string 9 | middlewareHandler []apinto_module.MiddlewareHandler 10 | routersInfo apinto_module.RoutersInfo 11 | } 12 | 13 | func (m *rModule) RoutersInfo() apinto_module.RoutersInfo { 14 | return m.routersInfo 15 | } 16 | 17 | func (m *rModule) Name() string { 18 | return m.name 19 | } 20 | 21 | func (m *rModule) Routers() (apinto_module.Routers, bool) { 22 | if len(m.routersInfo) == 0 { 23 | return nil, false 24 | } 25 | return m, true 26 | } 27 | 28 | func (m *rModule) Middleware() (apinto_module.Middleware, bool) { 29 | return nil, false 30 | } 31 | 32 | func (m *rModule) Support() (apinto_module.ProviderSupport, bool) { 33 | return nil, false 34 | } 35 | -------------------------------------------------------------------------------- /report/env.go: -------------------------------------------------------------------------------- 1 | package report 2 | 3 | import "time" 4 | 5 | const ( 6 | reportAddr = "https://statistics.apinto.com" 7 | periodTime = time.Hour * 24 8 | ) 9 | -------------------------------------------------------------------------------- /scripts/Dockerfile: -------------------------------------------------------------------------------- 1 | # 名称:apinto通用镜像 2 | # 创建时间:2022-10-25 3 | FROM centos:7.9.2009 4 | MAINTAINER liujian 5 | 6 | ENV TZ=Asia/Shanghai 7 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 8 | 9 | ARG APP 10 | ARG VERSION 11 | ARG DIR 12 | 13 | RUN mkdir -p /${APP} 14 | 15 | COPY ${DIR}/${APP}_${VERSION}_linux_amd64.tar.gz /${APP} 16 | 17 | RUN cd /${APP} && tar -zxvf ${APP}_${VERSION}_linux_amd64.tar.gz && rm -rf ${APP}_${VERSION}_linux_amd64.tar.gz && ln -snF ${APP}_${VERSION} ${APP} 18 | 19 | WORKDIR /$APP/$APP 20 | 21 | CMD ./docker_run.sh -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | ## 编译说明 2 | ### Docker打包指令 3 | ```shell 4 | ./docker_build.sh all {输出目录} {平台} 5 | ``` 6 | 示例 7 | ```shell 8 | ./docker_build.sh all apserver mac 9 | ``` -------------------------------------------------------------------------------- /scripts/docker_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # =========================================================================== 3 | # File: build.sh 4 | # Description: usage: ./build.sh [outdir] 5 | # =========================================================================== 6 | 7 | # exit when any command fails 8 | set -e 9 | 10 | cd "$(dirname "$0")/../" 11 | . ./scripts/init.sh 12 | 13 | #VERSION=`git describe --abbrev=0 --tags` 14 | MODE=$1 15 | OUTPUT_DIR=$(mkdir_output "$2") 16 | PLATFORM=$3 17 | OPTIONS="" 18 | if [[ "${PLATFORM}" == "mac" ]];then 19 | OPTIONS="--platform=linux/amd64" 20 | fi 21 | 22 | # 编译 23 | ./scripts/build.sh ${OUTPUT_DIR} ${MODE} ${VERSION} 24 | 25 | docker build ${OPTIONS} -t docker.eolinker.com/docker/apinto/apserver:${VERSION} --build-arg VERSION=${VERSION} --build-arg APP="apserver" --build-arg DIR=${OUTPUT_DIR} -f scripts/Dockerfile ./ 26 | 27 | -------------------------------------------------------------------------------- /scripts/docker_publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # =========================================================================== 3 | # File: build.sh 4 | # Description: usage: ./build.sh [outdir] 5 | # =========================================================================== 6 | 7 | # exit when any command fails 8 | set -e 9 | 10 | cd "$(dirname "$0")/../" 11 | . ./scripts/init.sh 12 | 13 | docker tag docker.eolinker.com/docker/apinto/apserver:${VERSION} docker.eolinker.com/docker/apinto/apserver:latest 14 | docker push docker.eolinker.com/docker/apinto/apserver:${VERSION} 15 | docker push docker.eolinker.com/docker/apinto/apserver:latest 16 | -------------------------------------------------------------------------------- /scripts/init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # =========================================================================== 3 | # File: init.sh 4 | # Description: common variables & functions. 5 | # =========================================================================== 6 | 7 | set -e 8 | 9 | # Global variables 10 | RED='\033[0;31m' 11 | GREEN='\033[0;32m' 12 | NC='\033[0m' # No Color 13 | 14 | # Invoke from project root 15 | VERSION=`git describe --abbrev=0 --tags` 16 | 17 | # Version function used for version string comparison 18 | version() { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; } 19 | 20 | # Ensure output directory existed 21 | mkdir_output() { 22 | if [ -z "$1" ]; then 23 | mkdir -p apinto-build 24 | OUTPUT_DIR=$(cd apinto-build > /dev/null && pwd) 25 | else 26 | OUTPUT_DIR="$1" 27 | fi 28 | echo "$OUTPUT_DIR" 29 | } -------------------------------------------------------------------------------- /scripts/resource/config.yml.tpl: -------------------------------------------------------------------------------- 1 | port: 服务监听的端口号 2 | mysql: 3 | user_name: "数据库用户名" 4 | password: "数据库密码" 5 | ip: "数据库IP地址" 6 | port: 端口号 7 | db: "数据库DB" 8 | error_log: 9 | dir: work/logs # 日志放置目录, 仅支持绝对路径, 不填则默认为执行程序上一层目录的work/logs. 若填写的值不为绝对路径,则以上一层目录为相对路径的根目录,比如填写 work/test/logs, 则目录为可执行程序所在目录的 ../work/test/logs 10 | file_name: error.log # 错误日志文件名 11 | log_level: warning # 错误日志等级,可选:panic,fatal,error,warning,info,debug,trace 不填或者非法则为info 12 | log_expire: 7d # 错误日志过期时间,默认单位为天,d|天,h|小时, 不合法配置默认为7d 13 | log_period: day # 错误日志切割周期,仅支持day、hour 14 | redis: 15 | user_name: "redis集群密码" 16 | password: "redis集群密码" 17 | addr: 18 | - 192.168.128.198:7201 19 | - 192.168.128.198:7202 -------------------------------------------------------------------------------- /store/init.go: -------------------------------------------------------------------------------- 1 | package store 2 | 3 | import ( 4 | "github.com/eolinker/eosc/common/bean" 5 | ) 6 | 7 | func InitStoreDB(db IDB) { 8 | 9 | bean.Injection(&db) 10 | runHandler(db) 11 | 12 | } 13 | -------------------------------------------------------------------------------- /store/page.go: -------------------------------------------------------------------------------- 1 | package store 2 | 3 | // PageIndex 用于gorm MYSQL 分页查询 4 | // 示例如下 5 | // db.Limit(pageSize).Offset(entry.PageIndex(pageNum,pageSize)) 6 | func PageIndex(pageNum, pageSize int) int { 7 | if pageNum == 0 { 8 | pageNum = 1 9 | } 10 | return (pageNum - 1) * pageSize 11 | } 12 | -------------------------------------------------------------------------------- /store/register.go: -------------------------------------------------------------------------------- 1 | package store 2 | 3 | type Handler func(db IDB) 4 | 5 | var ( 6 | handlers []Handler 7 | ) 8 | 9 | func RegisterStore(h Handler) { 10 | handlers = append(handlers, h) 11 | } 12 | func runHandler(db IDB) { 13 | for _, h := range handlers { 14 | h(db) 15 | } 16 | } 17 | --------------------------------------------------------------------------------