├── .env ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── 1bug.yaml │ ├── 2feature.yaml │ ├── 3consultation.yaml │ ├── bug.yaml │ ├── config.yml │ ├── consultation.yaml │ └── feature.yaml └── workflows │ ├── codeql-analysis.yml │ └── docker-build-and-release.yaml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── Makefile ├── Makefile.variable ├── README.md ├── cmdb-api ├── .env ├── .ruff.toml ├── Pipfile ├── api │ ├── __init__.py │ ├── app.py │ ├── commands │ │ ├── __init__.py │ │ ├── click_acl.py │ │ ├── click_cmdb.py │ │ ├── click_common_setting.py │ │ └── common.py │ ├── extensions.py │ ├── lib │ │ ├── __init__.py │ │ ├── cmdb │ │ │ ├── __init__.py │ │ │ ├── attribute.py │ │ │ ├── auto_discovery │ │ │ │ ├── __init__.py │ │ │ │ ├── auto_discovery.py │ │ │ │ ├── const.py │ │ │ │ └── templates │ │ │ │ │ ├── aliyun_ecs.json │ │ │ │ │ ├── aws_ec2.json │ │ │ │ │ ├── huaweicloud_ecs.json │ │ │ │ │ ├── net_device.json │ │ │ │ │ └── tencent_cvm.json │ │ │ ├── cache.py │ │ │ ├── ci.py │ │ │ ├── ci_type.py │ │ │ ├── const.py │ │ │ ├── custom_dashboard.py │ │ │ ├── dcim │ │ │ │ ├── __init__.py │ │ │ │ ├── base.py │ │ │ │ ├── const.py │ │ │ │ ├── history.py │ │ │ │ ├── idc.py │ │ │ │ ├── rack.py │ │ │ │ ├── region.py │ │ │ │ ├── server_room.py │ │ │ │ └── tree_view.py │ │ │ ├── history.py │ │ │ ├── ipam │ │ │ │ ├── __init__.py │ │ │ │ ├── address.py │ │ │ │ ├── const.py │ │ │ │ ├── history.py │ │ │ │ ├── stats.py │ │ │ │ └── subnet.py │ │ │ ├── perms.py │ │ │ ├── preference.py │ │ │ ├── query_sql.py │ │ │ ├── relation_type.py │ │ │ ├── resp_format.py │ │ │ ├── search │ │ │ │ ├── __init__.py │ │ │ │ ├── ci │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── db │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── query_sql.py │ │ │ │ │ │ └── search.py │ │ │ │ │ └── es │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ └── search.py │ │ │ │ └── ci_relation │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── search.py │ │ │ ├── topology.py │ │ │ ├── utils.py │ │ │ └── value.py │ │ ├── common_setting │ │ │ ├── __init__.py │ │ │ ├── acl.py │ │ │ ├── common_data.py │ │ │ ├── company_info.py │ │ │ ├── const.py │ │ │ ├── decorator.py │ │ │ ├── department.py │ │ │ ├── employee.py │ │ │ ├── notice_config.py │ │ │ ├── resp_format.py │ │ │ ├── role_perm_base.py │ │ │ ├── upload_file.py │ │ │ └── utils.py │ │ ├── const.py │ │ ├── database.py │ │ ├── decorator.py │ │ ├── exception.py │ │ ├── http_cli.py │ │ ├── mail.py │ │ ├── mixin.py │ │ ├── notify.py │ │ ├── perm │ │ │ ├── __init__.py │ │ │ ├── acl │ │ │ │ ├── __init__.py │ │ │ │ ├── acl.py │ │ │ │ ├── app.py │ │ │ │ ├── audit.py │ │ │ │ ├── cache.py │ │ │ │ ├── const.py │ │ │ │ ├── permission.py │ │ │ │ ├── record.py │ │ │ │ ├── resource.py │ │ │ │ ├── resp_format.py │ │ │ │ ├── role.py │ │ │ │ ├── trigger.py │ │ │ │ └── user.py │ │ │ ├── auth.py │ │ │ └── authentication │ │ │ │ ├── __init__.py │ │ │ │ ├── cas │ │ │ │ ├── __init__.py │ │ │ │ ├── cas_urls.py │ │ │ │ └── routing.py │ │ │ │ ├── ldap.py │ │ │ │ └── oauth2 │ │ │ │ ├── __init__.py │ │ │ │ └── routing.py │ │ ├── resp_format.py │ │ ├── secrets │ │ │ ├── __init__.py │ │ │ ├── inner.py │ │ │ ├── secrets.py │ │ │ └── vault.py │ │ ├── utils.py │ │ └── webhook.py │ ├── models │ │ ├── __init__.py │ │ ├── acl.py │ │ ├── cmdb.py │ │ └── common_setting.py │ ├── resource.py │ ├── tasks │ │ ├── __init__.py │ │ ├── acl.py │ │ ├── cmdb.py │ │ └── common_setting.py │ ├── translations │ │ └── zh │ │ │ └── LC_MESSAGES │ │ │ ├── messages.mo │ │ │ └── messages.po │ └── views │ │ ├── __init__.py │ │ ├── account.py │ │ ├── acl │ │ ├── __init__.py │ │ ├── app.py │ │ ├── audit.py │ │ ├── login.py │ │ ├── permission.py │ │ ├── resources.py │ │ ├── role.py │ │ ├── trigger.py │ │ └── user.py │ │ ├── cmdb │ │ ├── __init__.py │ │ ├── attribute.py │ │ ├── auto_discovery.py │ │ ├── c_stats.py │ │ ├── ci.py │ │ ├── ci_relation.py │ │ ├── ci_type.py │ │ ├── ci_type_relation.py │ │ ├── custom_dashboard.py │ │ ├── dcim │ │ │ ├── __init__.py │ │ │ ├── dcim_history.py │ │ │ ├── idc.py │ │ │ ├── rack.py │ │ │ ├── region.py │ │ │ ├── server_room.py │ │ │ └── tree_view.py │ │ ├── history.py │ │ ├── inner_secrets.py │ │ ├── ipam │ │ │ ├── __init__.py │ │ │ ├── address.py │ │ │ ├── ipam_history.py │ │ │ ├── ipam_stats.py │ │ │ └── subnet.py │ │ ├── preference.py │ │ ├── relation_type.py │ │ └── topology.py │ │ ├── common_setting │ │ ├── __init__.py │ │ ├── auth_config.py │ │ ├── common_data.py │ │ ├── company_info.py │ │ ├── department.py │ │ ├── employee.py │ │ ├── file_manage.py │ │ └── notice_config.py │ │ └── entry.py ├── autoapp.py ├── babel.cfg ├── celery_worker.py ├── logs │ └── .gitkeep ├── migrations │ ├── README │ ├── alembic.ini │ ├── env.py │ ├── script.py.mako │ └── versions │ │ └── 6a4df2623057_.py ├── requirements.txt ├── settings.example.py └── tests │ ├── __init__.py │ ├── conftest.py │ ├── sample.py │ ├── test_cmdb_attribute.py │ ├── test_cmdb_ci.py │ ├── test_cmdb_ci_realtion.py │ ├── test_cmdb_ci_type.py │ ├── test_cmdb_ci_type_relation.py │ ├── test_cmdb_history.py │ ├── test_cmdb_preference.py │ └── test_cmdb_relation_type.py ├── cmdb-ui ├── .editorconfig ├── .env ├── .env.preview ├── .eslintignore ├── .eslintrc.js ├── .prettierrc ├── .travis.yml ├── babel.config.js ├── config │ └── plugin.config.js ├── jest.config.js ├── jsconfig.json ├── package.json ├── postcss.config.js ├── public │ ├── color.less │ ├── iconfont │ │ ├── demo.css │ │ ├── demo_index.html │ │ ├── iconfont.css │ │ ├── iconfont.js │ │ ├── iconfont.json │ │ ├── iconfont.ttf │ │ ├── iconfont.woff │ │ └── iconfont.woff2 │ ├── index.html │ ├── loading │ │ ├── loading.css │ │ ├── loading.html │ │ └── option2 │ │ │ ├── html_code_segment.html │ │ │ ├── loading.css │ │ │ └── loading.svg │ └── logo.png ├── src │ ├── App.vue │ ├── api │ │ ├── auth.js │ │ ├── cmdb.js │ │ ├── company.js │ │ ├── employee.js │ │ ├── file.js │ │ ├── index.js │ │ ├── login.js │ │ ├── message.js │ │ └── noticeSetting.js │ ├── assets │ │ ├── background.svg │ │ ├── data_empty.png │ │ ├── file_upload.png │ │ ├── icon-bg-selected.png │ │ ├── icon-bg.png │ │ ├── icons │ │ │ ├── grid.svg │ │ │ ├── ops-move-icon.svg │ │ │ ├── top_acl.svg │ │ │ └── top_agent.svg │ │ ├── login_bg.png │ │ ├── login_img.png │ │ ├── logo.png │ │ ├── logo_VECMDB.png │ │ ├── ops_logout.png │ │ ├── sidebar_background.png │ │ └── sidebar_selected.png │ ├── bus │ │ └── index.js │ ├── components │ │ ├── CMDBExprDrawer │ │ │ ├── index.js │ │ │ └── index.vue │ │ ├── CMDBFilterComp │ │ │ ├── constants.js │ │ │ ├── expression.vue │ │ │ └── index.vue │ │ ├── CMDBValueTypeMapIcon │ │ │ └── index.vue │ │ ├── CardTitle │ │ │ ├── CardTitle.vue │ │ │ └── index.js │ │ ├── CollapseTransition │ │ │ └── index.vue │ │ ├── Crontab │ │ │ ├── Crontab-Day.vue │ │ │ ├── Crontab-Hour.vue │ │ │ ├── Crontab-Min.vue │ │ │ ├── Crontab-Mouth.vue │ │ │ ├── Crontab-Result.vue │ │ │ ├── Crontab-Second.vue │ │ │ ├── Crontab-Week.vue │ │ │ ├── Crontab-Year.vue │ │ │ ├── Crontab.vue │ │ │ ├── index.js │ │ │ └── utils │ │ │ │ └── index.js │ │ ├── CustomCodeMirror │ │ │ ├── index.js │ │ │ └── index.vue │ │ ├── CustomDrawer │ │ │ ├── CustomDrawer.vue │ │ │ └── index.js │ │ ├── CustomIconSelect │ │ │ ├── constants.js │ │ │ ├── index.js │ │ │ └── index.vue │ │ ├── CustomRadio │ │ │ ├── CustomRadio.vue │ │ │ └── index.js │ │ ├── CustomTransfer │ │ │ ├── CustomTransfer.vue │ │ │ └── index.js │ │ ├── EmployeeTransfer │ │ │ ├── index.js │ │ │ └── index.vue │ │ ├── Exception │ │ │ ├── ExceptionPage.vue │ │ │ ├── index.js │ │ │ └── type.js │ │ ├── GlobalFooter │ │ │ ├── GlobalFooter.vue │ │ │ └── index.js │ │ ├── GlobalHeader │ │ │ ├── GlobalHeader.vue │ │ │ └── index.js │ │ ├── Menu │ │ │ ├── SideMenu.vue │ │ │ ├── index.js │ │ │ ├── index.module.less │ │ │ └── menu.js │ │ ├── MonitorNodeSetting │ │ │ ├── index.js │ │ │ └── index.vue │ │ ├── MultiTab │ │ │ ├── MultiTab.vue │ │ │ ├── index.js │ │ │ └── index.less │ │ ├── OpsTable │ │ │ ├── index.js │ │ │ └── index.vue │ │ ├── PageHeader │ │ │ ├── PageHeader.vue │ │ │ └── index.js │ │ ├── PageLoading │ │ │ └── index.jsx │ │ ├── Pager │ │ │ ├── index.js │ │ │ └── index.vue │ │ ├── RegexSelect │ │ │ ├── constants.js │ │ │ ├── index.js │ │ │ └── regexSelect.vue │ │ ├── Result │ │ │ ├── Result.vue │ │ │ └── index.js │ │ ├── RoleTransfer │ │ │ ├── index.js │ │ │ └── index.vue │ │ ├── SettingDrawer │ │ │ ├── SettingDrawer.vue │ │ │ ├── SettingItem.vue │ │ │ ├── index.js │ │ │ ├── settingConfig.js │ │ │ └── themeColor.js │ │ ├── SidebarList │ │ │ ├── SidebarList.vue │ │ │ └── index.js │ │ ├── SplitPane │ │ │ ├── SplitPane.vue │ │ │ ├── index.js │ │ │ └── index.less │ │ ├── TagSelect │ │ │ ├── TagSelectOption.jsx │ │ │ └── index.jsx │ │ ├── TwoColumnLayout │ │ │ ├── TwoColumnLayout.vue │ │ │ └── index.js │ │ ├── _util │ │ │ └── util.js │ │ ├── ciReferenceAttr │ │ │ └── index.vue │ │ ├── index.js │ │ ├── index.less │ │ └── tools │ │ │ ├── Breadcrumb.vue │ │ │ ├── DetailList.vue │ │ │ ├── DocumentLink.vue │ │ │ ├── HeadInfo.vue │ │ │ ├── Logo.vue │ │ │ ├── TopMenu.vue │ │ │ ├── TwoStepCaptcha.vue │ │ │ ├── UserMenu.vue │ │ │ ├── index.js │ │ │ └── userPanel.vue │ ├── config │ │ ├── app.js │ │ └── setting.js │ ├── core │ │ ├── EventBus.js │ │ ├── bootstrap.js │ │ ├── directives │ │ │ └── action.js │ │ ├── icons.js │ │ ├── lazy_lib │ │ │ └── components_use.js │ │ ├── lazy_use.js │ │ └── use.js │ ├── directive │ │ ├── highlight │ │ │ ├── highlight.js │ │ │ ├── highlight.less │ │ │ └── index.js │ │ └── waves │ │ │ ├── index.js │ │ │ ├── waves.css │ │ │ └── waves.js │ ├── guard.js │ ├── lang │ │ ├── en.js │ │ ├── index.js │ │ └── zh.js │ ├── layouts │ │ ├── BasicLayout.vue │ │ ├── BlankLayout.vue │ │ ├── PageView.vue │ │ ├── RouteView.vue │ │ ├── UserLayout.vue │ │ └── index.js │ ├── main.js │ ├── modules │ │ ├── acl │ │ │ ├── api │ │ │ │ ├── app.js │ │ │ │ ├── history.js │ │ │ │ ├── permission.js │ │ │ │ ├── resource.js │ │ │ │ ├── role.js │ │ │ │ ├── secretKey.js │ │ │ │ ├── trigger.js │ │ │ │ └── user.js │ │ │ ├── constants │ │ │ │ └── constants.js │ │ │ ├── index.js │ │ │ ├── lang │ │ │ │ ├── en.js │ │ │ │ └── zh.js │ │ │ ├── router │ │ │ │ └── index.js │ │ │ ├── store │ │ │ │ └── index.js │ │ │ ├── style │ │ │ │ ├── index.css │ │ │ │ └── index.less │ │ │ └── views │ │ │ │ ├── apps.vue │ │ │ │ ├── history.vue │ │ │ │ ├── module │ │ │ │ ├── appForm.vue │ │ │ │ ├── permCollectForm.vue │ │ │ │ ├── permissionForm.vue │ │ │ │ ├── permissionHistoryTable.vue │ │ │ │ ├── resourceBatchPerm.vue │ │ │ │ ├── resourceForm.vue │ │ │ │ ├── resourceGroupMember.vue │ │ │ │ ├── resourceGroupModal.vue │ │ │ │ ├── resourceHistoryTable.vue │ │ │ │ ├── resourcePermForm.vue │ │ │ │ ├── resourcePermManageForm.vue │ │ │ │ ├── resourceTypeForm.vue │ │ │ │ ├── resourceTypeHistoryTable.vue │ │ │ │ ├── resourceUserForm.vue │ │ │ │ ├── roleForm.vue │ │ │ │ ├── roleHistoryTable.vue │ │ │ │ ├── searchForm.vue │ │ │ │ ├── triggerForm.vue │ │ │ │ ├── triggerHistoryTable.vue │ │ │ │ ├── triggerPattern.vue │ │ │ │ ├── userForm.vue │ │ │ │ └── usersUnderRoleForm.vue │ │ │ │ ├── operation_history │ │ │ │ ├── index.vue │ │ │ │ └── modules │ │ │ │ │ ├── permissionTable.vue │ │ │ │ │ ├── resourceHistoryTable.vue │ │ │ │ │ ├── resourceTypeHistoryTable.vue │ │ │ │ │ ├── roleHistoryTable.vue │ │ │ │ │ └── triggerHistoryTable.vue │ │ │ │ ├── resource_types.vue │ │ │ │ ├── resources.vue │ │ │ │ ├── roles.vue │ │ │ │ ├── secretKey.vue │ │ │ │ ├── trigger.vue │ │ │ │ └── users.vue │ │ └── cmdb │ │ │ ├── 3rd │ │ │ └── relation-graph │ │ │ │ ├── GraphBottomPanel.vue │ │ │ │ ├── GraphMiniNameFilter.vue │ │ │ │ ├── GraphMiniToolBar.vue │ │ │ │ ├── GraphMiniView.vue │ │ │ │ ├── GraphSettingPanel.vue │ │ │ │ ├── core4vue │ │ │ │ ├── SeeksGraphIconfont.js │ │ │ │ ├── SeeksGraphMath.js │ │ │ │ ├── SeeksRGLayouters.js │ │ │ │ ├── SeeksRGLink.vue │ │ │ │ ├── SeeksRGNode.vue │ │ │ │ ├── SeeksRGStore.js │ │ │ │ ├── SeeksRGUtils.js │ │ │ │ └── layouters │ │ │ │ │ ├── SeeksAutoLayouter.js │ │ │ │ │ ├── SeeksBidirectionalTreeLayouter.js │ │ │ │ │ ├── SeeksCenterLayouter.js │ │ │ │ │ ├── SeeksCircleLayouter.js │ │ │ │ │ └── SeeksFixedLayouter.js │ │ │ │ ├── index.js │ │ │ │ └── index.vue │ │ │ ├── api │ │ │ ├── CIRelation.js │ │ │ ├── CIType.js │ │ │ ├── CITypeAttr.js │ │ │ ├── CITypeRelation.js │ │ │ ├── batch.js │ │ │ ├── ci.js │ │ │ ├── ciTypeGroup.js │ │ │ ├── customDashboard.js │ │ │ ├── dcim.js │ │ │ ├── discovery.js │ │ │ ├── history.js │ │ │ ├── ipam.js │ │ │ ├── perm.js │ │ │ ├── preference.js │ │ │ ├── relationType.js │ │ │ ├── statistics.js │ │ │ ├── system_config.js │ │ │ └── topology.js │ │ │ ├── assets │ │ │ ├── dashboard_empty.png │ │ │ ├── dcim │ │ │ │ ├── dcim_null.png │ │ │ │ ├── device │ │ │ │ │ ├── firewall_front.png │ │ │ │ │ ├── firewall_rear.png │ │ │ │ │ ├── raid_front.png │ │ │ │ │ ├── raid_rear.png │ │ │ │ │ ├── router_front.png │ │ │ │ │ ├── router_rear.png │ │ │ │ │ ├── server_front.png │ │ │ │ │ ├── server_rear.png │ │ │ │ │ ├── switch_front.png │ │ │ │ │ └── switch_rear.png │ │ │ │ ├── device_2.png │ │ │ │ ├── rack.png │ │ │ │ ├── rack_front_part.png │ │ │ │ └── rack_rear_part.png │ │ │ ├── ipam_address_null.png │ │ │ ├── itsm_uninstalled.png │ │ │ ├── no_permission.png │ │ │ ├── preference_background.png │ │ │ ├── preference_card.png │ │ │ ├── resourceSearch │ │ │ │ ├── resource_search_bg_1.png │ │ │ │ └── resource_search_bg_2.png │ │ │ └── unique_card.png │ │ │ ├── components │ │ │ ├── JsonEditor │ │ │ │ └── jsonEditor.vue │ │ │ ├── attrMapTable │ │ │ │ └── index.vue │ │ │ ├── attributesTransfer │ │ │ │ └── index.vue │ │ │ ├── batchDownload │ │ │ │ └── batchDownload.vue │ │ │ ├── ciIcon │ │ │ │ └── index.vue │ │ │ ├── ciTable │ │ │ │ └── index.vue │ │ │ ├── cmdbGrant │ │ │ │ ├── ciTypeGrant.vue │ │ │ │ ├── constants.js │ │ │ │ ├── grantComp.vue │ │ │ │ ├── grantModal.vue │ │ │ │ ├── index.vue │ │ │ │ ├── readCheckbox.vue │ │ │ │ ├── readGrantModal.vue │ │ │ │ ├── relationViewGrant.vue │ │ │ │ ├── revokeModal.vue │ │ │ │ ├── topologyViewGrant.vue │ │ │ │ ├── typeRelationGrant.vue │ │ │ │ └── utils.js │ │ │ ├── cmdbTypeSelect │ │ │ │ ├── cmdbTypeSelect.vue │ │ │ │ └── index.js │ │ │ ├── colorPicker │ │ │ │ └── index.vue │ │ │ ├── conditionFilter │ │ │ │ ├── constants.js │ │ │ │ ├── expression.vue │ │ │ │ ├── index.vue │ │ │ │ └── valueControls.vue │ │ │ ├── httpSnmpAD │ │ │ │ ├── adPreviewTable.vue │ │ │ │ ├── httpADCategory.vue │ │ │ │ └── index.vue │ │ │ ├── noticeContent │ │ │ │ ├── index.js │ │ │ │ └── index.vue │ │ │ ├── passwordField │ │ │ │ └── index.vue │ │ │ ├── preferenceSearch │ │ │ │ └── preferenceSearch.vue │ │ │ ├── searchForm │ │ │ │ └── SearchForm.vue │ │ │ ├── subscribeSetting │ │ │ │ └── subscribeSetting.vue │ │ │ └── webhook │ │ │ │ ├── authorization.vue │ │ │ │ ├── body.vue │ │ │ │ ├── header.vue │ │ │ │ ├── index.js │ │ │ │ ├── index.vue │ │ │ │ └── paramaters.vue │ │ │ ├── index.js │ │ │ ├── lang │ │ │ ├── en.js │ │ │ └── zh.js │ │ │ ├── router │ │ │ └── index.js │ │ │ ├── store │ │ │ └── index.js │ │ │ ├── utils │ │ │ ├── const.js │ │ │ └── helper.js │ │ │ └── views │ │ │ ├── batch │ │ │ ├── index.vue │ │ │ └── modules │ │ │ │ ├── CiTypeChoice.vue │ │ │ │ ├── CiUploadTable.vue │ │ │ │ ├── UploadFileForm.vue │ │ │ │ └── UploadResult.vue │ │ │ ├── ci │ │ │ ├── ciDetailPage.vue │ │ │ ├── index.vue │ │ │ └── modules │ │ │ │ ├── BatchUpdateRelation.vue │ │ │ │ ├── CreateInstanceForm.vue │ │ │ │ ├── MetadataDrawer.vue │ │ │ │ ├── ciDetailAttrContent.vue │ │ │ │ ├── ciDetailComponent │ │ │ │ ├── ciDetailTableTitle.vue │ │ │ │ ├── ciDetailTitle.vue │ │ │ │ └── ciRelationTable.vue │ │ │ │ ├── ciDetailDrawer.vue │ │ │ │ ├── ciDetailMixin │ │ │ │ └── relationMixin.js │ │ │ │ ├── ciDetailRelatedItsmTable.vue │ │ │ │ ├── ciDetailRelation.vue │ │ │ │ ├── ciDetailRelationTopo │ │ │ │ ├── index.less │ │ │ │ ├── index.vue │ │ │ │ └── node.js │ │ │ │ ├── ciDetailTab.vue │ │ │ │ ├── ciRollbackForm.vue │ │ │ │ ├── createInstanceFormByGroup.vue │ │ │ │ └── editAttrsPopover.vue │ │ │ ├── ci_types │ │ │ ├── adModal.vue │ │ │ ├── adTab.vue │ │ │ ├── allAttrDrawer.vue │ │ │ ├── attrAD.vue │ │ │ ├── attrAD │ │ │ │ ├── SNMPConfig │ │ │ │ │ └── index.vue │ │ │ │ ├── SNMPScanningConfig │ │ │ │ │ └── index.vue │ │ │ │ ├── cidrTags │ │ │ │ │ └── index.vue │ │ │ │ ├── cloudTab │ │ │ │ │ └── index.vue │ │ │ │ ├── constants.js │ │ │ │ ├── nodeSetting │ │ │ │ │ └── index.vue │ │ │ │ ├── portScanConfig │ │ │ │ │ └── index.vue │ │ │ │ ├── privateCloud │ │ │ │ │ └── vcenterForm.vue │ │ │ │ └── publicCloud │ │ │ │ │ └── index.vue │ │ │ ├── attrADTabpane.vue │ │ │ ├── attrADTabs.vue │ │ │ ├── attrADTest.vue │ │ │ ├── attributeCard.vue │ │ │ ├── attributeEdit │ │ │ │ └── referenceModelSelect.vue │ │ │ ├── attributeEditForm.vue │ │ │ ├── attributeStore.vue │ │ │ ├── attributesTable.vue │ │ │ ├── ceateNewAttribute.vue │ │ │ ├── ciTypedetail.vue │ │ │ ├── computedArea.vue │ │ │ ├── fontArea.vue │ │ │ ├── iconArea.vue │ │ │ ├── index.vue │ │ │ ├── modelExport.vue │ │ │ ├── newCiTypeAttrModal.vue │ │ │ ├── preValueArea.vue │ │ │ ├── preValueAttr │ │ │ │ ├── attrFilter │ │ │ │ │ ├── expression.vue │ │ │ │ │ ├── index.vue │ │ │ │ │ └── valueControls.vue │ │ │ │ ├── builtin │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── index.vue │ │ │ │ │ └── userFilterComp │ │ │ │ │ │ ├── constants.js │ │ │ │ │ │ ├── employeeTreeSelect.vue │ │ │ │ │ │ └── index.vue │ │ │ │ ├── constants.js │ │ │ │ └── define │ │ │ │ │ ├── defineLabel.vue │ │ │ │ │ └── index.vue │ │ │ ├── preValueTag.vue │ │ │ ├── relationAD.vue │ │ │ ├── relationTable.vue │ │ │ ├── triggerForm.vue │ │ │ ├── triggerTable.vue │ │ │ └── uniqueConstraint.vue │ │ │ ├── custom_dashboard │ │ │ ├── chart.vue │ │ │ ├── chartForm.vue │ │ │ ├── chartOptions.js │ │ │ ├── colorListPicker.vue │ │ │ ├── colorPicker.vue │ │ │ ├── constant.js │ │ │ ├── customLayout.vue │ │ │ ├── fontConfig.vue │ │ │ └── index.vue │ │ │ ├── dashboard │ │ │ ├── components │ │ │ │ ├── businessCounter.vue │ │ │ │ ├── dashboardCard.vue │ │ │ │ ├── summaryCounter.vue │ │ │ │ └── systemCounter.vue │ │ │ ├── constants.js │ │ │ ├── index.vue │ │ │ └── index_v2.vue │ │ │ ├── dcim │ │ │ ├── components │ │ │ │ ├── dcimForm.vue │ │ │ │ ├── dcimMain │ │ │ │ │ ├── dcimStats.vue │ │ │ │ │ ├── dcimStatsChart.vue │ │ │ │ │ ├── index.vue │ │ │ │ │ ├── rackGrid.vue │ │ │ │ │ └── rackTable.vue │ │ │ │ ├── dcimTree.vue │ │ │ │ └── rackDetail │ │ │ │ │ ├── deviceList │ │ │ │ │ └── index.vue │ │ │ │ │ ├── index.vue │ │ │ │ │ ├── operationLog │ │ │ │ │ └── index.vue │ │ │ │ │ ├── rackGroupAttr │ │ │ │ │ └── index.vue │ │ │ │ │ └── rackView │ │ │ │ │ ├── abnormalModal.vue │ │ │ │ │ ├── deviceForm │ │ │ │ │ ├── deviceSelect.vue │ │ │ │ │ └── index.vue │ │ │ │ │ ├── index.vue │ │ │ │ │ ├── migrateModal.vue │ │ │ │ │ ├── rackHeader │ │ │ │ │ ├── index.vue │ │ │ │ │ └── rackHeaderCircle.vue │ │ │ │ │ └── rackUnitView.vue │ │ │ ├── constants.js │ │ │ └── index.vue │ │ │ ├── discovery │ │ │ ├── accountConfig │ │ │ │ ├── constants.js │ │ │ │ ├── index.vue │ │ │ │ ├── publicTable.vue │ │ │ │ └── vcenterTable.vue │ │ │ ├── agentTable.vue │ │ │ ├── constants.js │ │ │ ├── discoveryCard.vue │ │ │ ├── editDrawer.vue │ │ │ └── index.vue │ │ │ ├── discoveryCI │ │ │ ├── components │ │ │ │ ├── adcCounter.vue │ │ │ │ └── passwordField.vue │ │ │ └── index.vue │ │ │ ├── fullscreen │ │ │ ├── assetsCard.vue │ │ │ ├── index.less │ │ │ ├── index.vue │ │ │ └── processLine.vue │ │ │ ├── index.less │ │ │ ├── ipam │ │ │ ├── components │ │ │ │ ├── catalogForm.vue │ │ │ │ ├── ipamTree.vue │ │ │ │ └── subnetForm.vue │ │ │ ├── constants.js │ │ │ ├── index.vue │ │ │ └── modules │ │ │ │ ├── address │ │ │ │ ├── assignForm.vue │ │ │ │ ├── constants.js │ │ │ │ ├── gridIP.vue │ │ │ │ ├── index.vue │ │ │ │ └── tableIP.vue │ │ │ │ ├── history │ │ │ │ ├── index.vue │ │ │ │ ├── operation │ │ │ │ │ ├── constants.js │ │ │ │ │ └── index.vue │ │ │ │ └── scan │ │ │ │ │ └── index.vue │ │ │ │ ├── ipSearch │ │ │ │ └── index.vue │ │ │ │ ├── overview │ │ │ │ ├── index.vue │ │ │ │ ├── stats.vue │ │ │ │ ├── statsChart.vue │ │ │ │ └── subnetTable.vue │ │ │ │ └── subnetList │ │ │ │ └── index.vue │ │ │ ├── model_relation │ │ │ ├── index.vue │ │ │ └── modules │ │ │ │ └── modelRelationTable.vue │ │ │ ├── operation_history │ │ │ ├── index.vue │ │ │ └── modules │ │ │ │ ├── ciTable.vue │ │ │ │ ├── relation.vue │ │ │ │ ├── searchForm.vue │ │ │ │ ├── triggerTable.vue │ │ │ │ └── typeTable.vue │ │ │ ├── preference │ │ │ └── index.vue │ │ │ ├── preference_relation │ │ │ ├── index.vue │ │ │ ├── modules │ │ │ │ └── RelationViewForm.vue │ │ │ └── serviceTreeModal.vue │ │ │ ├── relation_type │ │ │ └── index.vue │ │ │ ├── relation_views │ │ │ ├── index.vue │ │ │ └── modules │ │ │ │ ├── AddTableModal.vue │ │ │ │ ├── ContextMenu.vue │ │ │ │ └── ReadPermissionsModal.vue │ │ │ ├── resource_search │ │ │ └── index.vue │ │ │ ├── resource_search_2 │ │ │ ├── components │ │ │ │ ├── attrDisplay.vue │ │ │ │ ├── filterPopover.vue │ │ │ │ ├── historyList.vue │ │ │ │ ├── instanceDetail.vue │ │ │ │ ├── instanceList.vue │ │ │ │ └── searchInput.vue │ │ │ ├── index.vue │ │ │ ├── relationSearch │ │ │ │ ├── components │ │ │ │ │ ├── ciTable.vue │ │ │ │ │ ├── filterPopover.vue │ │ │ │ │ ├── saveConditionModal.vue │ │ │ │ │ └── searchCondition.vue │ │ │ │ └── index.vue │ │ │ └── resourceSearch │ │ │ │ ├── components │ │ │ │ ├── attrDisplay.vue │ │ │ │ ├── filterPopover.vue │ │ │ │ ├── historyList.vue │ │ │ │ ├── instanceDetail.vue │ │ │ │ ├── instanceList.vue │ │ │ │ └── searchInput.vue │ │ │ │ ├── constants.js │ │ │ │ └── index.vue │ │ │ ├── topology_view │ │ │ └── index.vue │ │ │ └── tree_views │ │ │ ├── index.vue │ │ │ └── modules │ │ │ └── treeViewsNode.vue │ ├── router │ │ ├── config.js │ │ ├── index.js │ │ └── utils.js │ ├── store │ │ ├── global │ │ │ ├── app.js │ │ │ ├── company.js │ │ │ ├── getters.js │ │ │ ├── mutation-types.js │ │ │ ├── notice.js │ │ │ ├── routes.js │ │ │ └── user.js │ │ └── index.js │ ├── style │ │ ├── global.less │ │ ├── index.css │ │ ├── index.less │ │ └── static.less │ ├── utils │ │ ├── axios.js │ │ ├── device.js │ │ ├── domUtil.js │ │ ├── download.js │ │ ├── filter.js │ │ ├── functions │ │ │ └── set.js │ │ ├── helper │ │ │ └── permission.js │ │ ├── mixin.js │ │ ├── request.js │ │ ├── util.js │ │ ├── utils.css │ │ └── utils.less │ └── views │ │ ├── exception │ │ ├── 403.vue │ │ ├── 404.vue │ │ └── 500.vue │ │ ├── noticeCenter │ │ └── index.vue │ │ ├── setting │ │ ├── auth │ │ │ ├── cas.vue │ │ │ ├── common.vue │ │ │ ├── index.vue │ │ │ ├── ldap.vue │ │ │ ├── loginModal.vue │ │ │ └── oauth2.vue │ │ ├── companyInfo │ │ │ └── index.vue │ │ ├── companyStructure │ │ │ ├── BatchModal.vue │ │ │ ├── CategoryTree.vue │ │ │ ├── DepartmentModal.vue │ │ │ ├── EmployeeModal.vue │ │ │ ├── eventBus │ │ │ │ └── bus.js │ │ │ └── index.vue │ │ ├── components │ │ │ ├── BatchUpload.vue │ │ │ ├── EditImage.vue │ │ │ ├── SearchForm.vue │ │ │ ├── departmentTreeSelect.vue │ │ │ ├── employeeTable.vue │ │ │ ├── employeeTreeSelect.vue │ │ │ ├── relateEmployee.vue │ │ │ ├── settingFilterComp │ │ │ │ ├── constants.js │ │ │ │ └── index.vue │ │ │ └── spanTitle.vue │ │ ├── lang │ │ │ ├── en.js │ │ │ └── zh.js │ │ ├── notice │ │ │ ├── basic.vue │ │ │ └── email │ │ │ │ ├── index.less │ │ │ │ ├── index.vue │ │ │ │ ├── receive.vue │ │ │ │ └── send.vue │ │ └── person │ │ │ └── index.vue │ │ └── user │ │ ├── Login.vue │ │ ├── Logout.vue │ │ ├── Register.vue │ │ └── RegisterResult.vue ├── vue.config.js └── webstorm.config.js ├── docker-compose.yml ├── docker ├── Dockerfile-API └── Dockerfile-UI ├── docs ├── CONTRIBUTING.md ├── CONTRIBUTING_en.md ├── README_en.md ├── cmdb.sql ├── cmdb_api.md ├── cmdb_en.sql ├── cmdb_query_api.md ├── flask-migrate.md ├── images │ ├── logo.png │ ├── qr_code.jpg │ ├── qrcode_for_gzh.jpg │ ├── view.jpg │ └── wechat.png ├── local.md ├── local_en.md ├── makefile.md ├── makefile_en.md ├── mysqld.cnf └── nginx.cmdb.conf.example └── install.sh /.env: -------------------------------------------------------------------------------- 1 | MYSQL_ROOT_PASSWORD='123456' 2 | MYSQL_HOST='mysql' 3 | MYSQL_PORT=3306 4 | MYSQL_USER='cmdb' 5 | MYSQL_DATABASE='cmdb' 6 | MYSQL_PASSWORD='123456' 7 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.vue linguist-language=python 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2feature.yaml: -------------------------------------------------------------------------------- 1 | name: Feature wanted 2 | description: A new feature would be good 3 | title: "[Feature]: " 4 | labels: ["✏️ feature"] 5 | assignees: 6 | - pycook 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | Thank you for your feature suggestion; we will evaluate it carefully! 12 | - type: input 13 | id: contact 14 | attributes: 15 | label: Contact Details 16 | description: How can we get in touch with you if we need more info? 17 | placeholder: ex. email@example.com 18 | validations: 19 | required: false 20 | - type: dropdown 21 | id: aspects 22 | attributes: 23 | label: feature is related to UI or API aspects? 24 | multiple: true 25 | options: 26 | - UI 27 | - API 28 | - type: textarea 29 | id: feature 30 | attributes: 31 | label: What is your advice? 32 | description: Also tell us, what did you expect to happen? 33 | placeholder: Tell us what you want! 34 | value: "everyone wants this feature!" 35 | validations: 36 | required: true 37 | - type: input 38 | id: version 39 | attributes: 40 | label: Version 41 | description: What version of our software are you running? 42 | value: "newest" 43 | validations: 44 | required: true 45 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/3consultation.yaml: -------------------------------------------------------------------------------- 1 | name: Help wanted 2 | description: I have a question 3 | title: "[help wanted]: " 4 | labels: ["help wanted"] 5 | assignees: 6 | - ivonGwy 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | Please tell us what's you need! 12 | - type: input 13 | id: contact 14 | attributes: 15 | label: Contact Details 16 | description: How can we get in touch with you if we need more info? 17 | placeholder: ex. email@example.com 18 | validations: 19 | required: false 20 | - type: textarea 21 | id: question 22 | attributes: 23 | label: What is your question? 24 | description: Also tell us, how can we help? 25 | placeholder: Tell us what you need! 26 | value: "i have a question!" 27 | validations: 28 | required: true 29 | - type: input 30 | id: version 31 | attributes: 32 | label: Version 33 | description: What version of our software are you running? 34 | value: "newest" 35 | validations: 36 | required: true 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: veops official website 4 | url: https://veops.cn/#hero 5 | about: you can contact us here. 6 | 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/consultation.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/.github/ISSUE_TEMPLATE/consultation.yaml -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.yaml: -------------------------------------------------------------------------------- 1 | name: Feature wanted 2 | description: A new feature would be good 3 | title: "[Feature]: " 4 | labels: ["feature"] 5 | assignees: 6 | - pycook 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | Thank you for your feature suggestion; we will evaluate it carefully! 12 | - type: input 13 | id: contact 14 | attributes: 15 | label: Contact Details 16 | description: How can we get in touch with you if we need more info? 17 | placeholder: ex. email@example.com 18 | validations: 19 | required: false 20 | - type: dropdown 21 | id: type 22 | attributes: 23 | label: feature is related to UI or API aspects? 24 | multiple: true 25 | options: 26 | - UI 27 | - API 28 | - type: textarea 29 | id: describe the feature 30 | attributes: 31 | label: What is your advice? 32 | description: Also tell us, what did you expect to happen? 33 | placeholder: Tell us what you want! 34 | value: "everyone wants this feature!" 35 | validations: 36 | required: true 37 | - type: textarea 38 | id: version 39 | attributes: 40 | label: Version 41 | description: What version of our software are you running? 42 | default: 2.3.5 43 | validations: 44 | required: true 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .idea 3 | .vscode 4 | migrates 5 | config.cfg 6 | *.log 7 | *_packed.js 8 | *_packed.css 9 | *.orig 10 | *.zip 11 | nohup.out 12 | .DS_Store 13 | *.py[cod] 14 | 15 | # C extensions 16 | *.so 17 | 18 | # Packages 19 | *.egg 20 | *.egg-info 21 | build 22 | eggs 23 | parts 24 | bin 25 | var 26 | sdist 27 | develop-eggs 28 | .installed.cfg 29 | #lib 30 | #lib64 31 | Pipfile.lock 32 | 33 | # Installer logs 34 | pip-log.txt 35 | 36 | # Unit test / coverage reports 37 | .coverage 38 | .tox 39 | nosetests.xml 40 | .pytest_cache 41 | cmdb-api/test-output 42 | cmdb-api/api/uploaded_files 43 | cmdb-api/migrations/versions 44 | 45 | # Translations 46 | #*.mo 47 | messages.pot 48 | 49 | # Mr Developer 50 | .mr.developer.cfg 51 | .project 52 | .pydevproject 53 | 54 | # Complexity 55 | output/*.html 56 | output/*/index.html 57 | 58 | # Sphinx 59 | docs/_build 60 | 61 | # Virtualenvs 62 | env/ 63 | 64 | 65 | # Configuration 66 | settings.py 67 | 68 | # Development database 69 | *.db 70 | 71 | # UI 72 | cmdb-ui/node_modules 73 | cmdb-ui/dist 74 | cmdb-ui/yarn.lock 75 | 76 | # Log files 77 | cmdb-ui/npm-debug.log* 78 | cmdb-ui/yarn-debug.log* 79 | cmdb-ui/yarn-error.log* 80 | cmdb-ui/package-lock.json 81 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. 4 | 5 | We are committed to making participation in this project a harassment-free experience for everyone, regardless of the level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion. 6 | 7 | Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. 8 | 9 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team. 10 | 11 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. 12 | 13 | This Code of Conduct is adapted from the [Contributor Covenant](https://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/) -------------------------------------------------------------------------------- /Makefile.variable: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash -o pipefail 2 | 3 | MYSQL_ROOT_PASSWORD ?= root 4 | MYSQL_PORT ?= 3306 5 | REDIS_PORT ?= 6379 6 | 7 | LATEST_TAG_DIFF:=$(shell git describe --tags --abbrev=8) 8 | LATEST_COMMIT:=$(VERSION)-dev-$(shell git rev-parse --short=8 HEAD) 9 | BUILD_ARCH ?= linux/amd64,linux/arm64 10 | 11 | # Set your version by env or using latest tags from git 12 | CMDB_VERSION?=$(LATEST_TAG_DIFF) 13 | ifeq ($(CMDB_VERSION),) 14 | #fall back to last commit 15 | CMDB_VERSION=$(LATEST_COMMIT) 16 | endif 17 | COMMIT_VERSION:=$(LATEST_COMMIT) 18 | CMDB_DOCKER_VERSION:=${CMDB_VERSION} 19 | CMDB_CHART_VERSION:=$(shell echo ${CMDB_VERSION} | sed 's/^v//g' ) 20 | 21 | REGISTRY ?= local -------------------------------------------------------------------------------- /cmdb-api/.env: -------------------------------------------------------------------------------- 1 | # Environment variable overrides for local development 2 | FLASK_APP=autoapp.py 3 | FLASK_DEBUG=1 4 | FLASK_ENV=development 5 | GUNICORN_WORKERS=2 6 | LOG_LEVEL=debug 7 | SECRET_KEY='' 8 | -------------------------------------------------------------------------------- /cmdb-api/api/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/commands/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/extensions.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | from celery import Celery 5 | from flask_babel import Babel 6 | from flask_bcrypt import Bcrypt 7 | from flask_caching import Cache 8 | from flask_cors import CORS 9 | from flask_login import LoginManager 10 | from flask_migrate import Migrate 11 | from flask_sqlalchemy import SQLAlchemy 12 | 13 | from api.lib.secrets.inner import KeyManage 14 | from api.lib.utils import ESHandler 15 | from api.lib.utils import RedisHandler 16 | 17 | bcrypt = Bcrypt() 18 | babel = Babel() 19 | login_manager = LoginManager() 20 | db = SQLAlchemy(session_options={"autoflush": False}) 21 | migrate = Migrate() 22 | cache = Cache() 23 | celery = Celery() 24 | cors = CORS(supports_credentials=True) 25 | rd = RedisHandler() 26 | es = ESHandler() 27 | inner_secrets = KeyManage() 28 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/auto_discovery/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/auto_discovery/templates/net_device.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "manufacturer", 4 | "type": "文本", 5 | "example": "Huawei", 6 | "desc": "制造产商" 7 | }, 8 | { 9 | "name": "sn", 10 | "type": "文本", 11 | "example": "102030059898", 12 | "desc": "设备序列号" 13 | }, 14 | { 15 | "name": "name", 16 | "type": "文本", 17 | "example": "USG6525E", 18 | "desc": "设备名称" 19 | }, 20 | { 21 | "name": "model", 22 | "type": "文本", 23 | "example": "2011.2.321.1.205", 24 | "desc": "设备细分类型 结合相关产商获取相应的产品类型" 25 | }, 26 | { 27 | "name": "description", 28 | "type": "文本", 29 | "example": "Huawei Vwersatile Routing Platform Software", 30 | "desc": "设备描述" 31 | }, 32 | { 33 | "name": "manager_ip", 34 | "type": "文本", 35 | "example": "192.168.1.1", 36 | "desc": "管理ip" 37 | }, 38 | { 39 | "name": "ips", 40 | "type": "文本、多值", 41 | "example": "192.168.1.1, 192.168.1.2", 42 | "desc": "ips" 43 | }, 44 | { 45 | "name": "uptime", 46 | "type": "文本", 47 | "example": "2023-04-15 10:00:00", 48 | "desc": "启动时间" 49 | }, 50 | { 51 | "name": "snmp_version", 52 | "type": "文本", 53 | "example": "v2c", 54 | "desc": "SNMP版本" 55 | }, 56 | { 57 | "name": "port_num", 58 | "type": "整数", 59 | "example": 24, 60 | "desc": "端口数量" 61 | }, 62 | { 63 | "name": "ports", 64 | "type": "json", 65 | "example": "", 66 | "desc": "设备的端口列表" 67 | }, 68 | { 69 | "name": "neighbors", 70 | "type": "json", 71 | "example": "", 72 | "desc": "设备的邻居列表" 73 | } 74 | ] -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/dcim/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/dcim/base.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from api.lib.cmdb.ci import CIManager 4 | from api.lib.cmdb.ci import CIRelationManager 5 | from api.lib.cmdb.const import ExistPolicy 6 | 7 | 8 | class DCIMBase(object): 9 | def __init__(self): 10 | self.type_id = None 11 | 12 | @staticmethod 13 | def add_relation(parent_id, child_id): 14 | if not parent_id or not child_id: 15 | return 16 | 17 | CIRelationManager().add(parent_id, child_id, valid=False, apply_async=False) 18 | 19 | def add(self, parent_id, **kwargs): 20 | ci_id = CIManager().add(self.type_id, exist_policy=ExistPolicy.REJECT, **kwargs) 21 | 22 | if parent_id: 23 | self.add_relation(parent_id, ci_id) 24 | 25 | return ci_id 26 | 27 | @classmethod 28 | def update(cls, _id, **kwargs): 29 | CIManager().update(_id, **kwargs) 30 | 31 | @classmethod 32 | def delete(cls, _id): 33 | CIManager().delete(_id) 34 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/dcim/const.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | from api.lib.utils import BaseEnum 5 | 6 | 7 | class RackBuiltinAttributes(BaseEnum): 8 | U_COUNT = 'u_count' 9 | U_START = 'u_start' 10 | FREE_U_COUNT = 'free_u_count' 11 | U_SLOT_ABNORMAL = 'u_slot_abnormal' 12 | 13 | 14 | class OperateTypeEnum(BaseEnum): 15 | ADD_DEVICE = "0" 16 | REMOVE_DEVICE = "1" 17 | MOVE_DEVICE = "2" 18 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/dcim/history.py: -------------------------------------------------------------------------------- 1 | from flask_login import current_user 2 | 3 | from api.lib.cmdb.cache import AttributeCache 4 | from api.lib.cmdb.cache import CITypeCache 5 | from api.lib.cmdb.ci import CIManager 6 | from api.lib.mixin import DBMixin 7 | from api.models.cmdb import DCIMOperationHistory 8 | 9 | 10 | class OperateHistoryManager(DBMixin): 11 | cls = DCIMOperationHistory 12 | 13 | @classmethod 14 | def search(cls, page, page_size, fl=None, only_query=False, reverse=False, count_query=False, 15 | last_size=None, **kwargs): 16 | numfound, result = super(OperateHistoryManager, cls).search(page, page_size, fl, only_query, reverse, 17 | count_query, last_size, **kwargs) 18 | 19 | ci_ids = [i['ci_id'] for i in result] 20 | id2ci = {i['_id']: i for i in (CIManager.get_cis_by_ids(ci_ids) or []) if i} 21 | type2show_key = dict() 22 | for i in id2ci.values(): 23 | if i.get('_type') not in type2show_key: 24 | ci_type = CITypeCache.get(i.get('_type')) 25 | if ci_type: 26 | show_key = AttributeCache.get(ci_type.show_id or ci_type.unique_id) 27 | type2show_key[i['_type']] = show_key and show_key.name 28 | 29 | return numfound, result, id2ci, type2show_key 30 | 31 | def _can_add(self, **kwargs): 32 | kwargs['uid'] = current_user.uid 33 | 34 | return kwargs 35 | 36 | def _can_update(self, **kwargs): 37 | pass 38 | 39 | def _can_delete(self, **kwargs): 40 | pass 41 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/dcim/idc.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | from flask import abort 5 | 6 | from api.lib.cmdb.cache import CITypeCache 7 | from api.lib.cmdb.const import BuiltinModelEnum 8 | from api.lib.cmdb.dcim.base import DCIMBase 9 | from api.lib.cmdb.resp_format import ErrFormat 10 | 11 | 12 | class IDCManager(DCIMBase): 13 | def __init__(self): 14 | super(IDCManager, self).__init__() 15 | 16 | self.ci_type = CITypeCache.get(BuiltinModelEnum.DCIM_IDC) or abort( 17 | 404, ErrFormat.dcim_builtin_model_not_found.format(BuiltinModelEnum.DCIM_IDC)) 18 | 19 | self.type_id = self.ci_type.id 20 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/dcim/region.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | from flask import abort 5 | 6 | from api.lib.cmdb.cache import CITypeCache 7 | from api.lib.cmdb.ci import CIManager 8 | from api.lib.cmdb.const import BuiltinModelEnum 9 | from api.lib.cmdb.const import ExistPolicy 10 | from api.lib.cmdb.resp_format import ErrFormat 11 | 12 | 13 | class RegionManager(object): 14 | def __init__(self): 15 | self.ci_type = CITypeCache.get(BuiltinModelEnum.DCIM_REGION) or abort( 16 | 404, ErrFormat.dcim_builtin_model_not_found.format(BuiltinModelEnum.DCIM_REGION)) 17 | 18 | self.type_id = self.ci_type.id 19 | 20 | def add(self, **kwargs): 21 | return CIManager().add(self.type_id, exist_policy=ExistPolicy.REJECT, **kwargs) 22 | 23 | @classmethod 24 | def update(cls, _id, **kwargs): 25 | CIManager().update(_id, **kwargs) 26 | 27 | @classmethod 28 | def delete(cls, _id): 29 | CIManager().delete(_id) 30 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/ipam/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/ipam/const.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from api.lib.utils import BaseEnum 4 | 5 | 6 | class IPAddressAssignStatus(BaseEnum): 7 | ASSIGNED = 0 8 | UNASSIGNED = 1 9 | RESERVED = 2 10 | 11 | 12 | class OperateTypeEnum(BaseEnum): 13 | ADD_SCOPE = "0" 14 | UPDATE_SCOPE = "1" 15 | DELETE_SCOPE = "2" 16 | ADD_SUBNET = "3" 17 | UPDATE_SUBNET = "4" 18 | DELETE_SUBNET = "5" 19 | ASSIGN_ADDRESS = "6" 20 | REVOKE_ADDRESS = "7" 21 | 22 | 23 | class SubnetBuiltinAttributes(BaseEnum): 24 | NAME = 'name' 25 | CIDR = 'cidr' 26 | HOSTS_COUNT = 'hosts_count' 27 | ASSIGN_COUNT = 'assign_count' 28 | USED_COUNT = 'used_count' 29 | FREE_COUNT = 'free_count' 30 | 31 | 32 | class IPAddressBuiltinAttributes(BaseEnum): 33 | IP = 'ip' 34 | ASSIGN_STATUS = 'assign_status' # enum: 0 - assigned 1 - unassigned 2 - reserved 35 | IS_USED = 'is_used' # bool 36 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/query_sql.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | QUERY_CIS_BY_VALUE_TABLE = """ 5 | SELECT attr.name AS attr_name, 6 | attr.alias AS attr_alias, 7 | attr.value_type, 8 | attr.is_list, 9 | c_cis.type_id, 10 | {0}.ci_id, 11 | {0}.attr_id, 12 | {0}.value 13 | FROM {0} 14 | INNER JOIN c_cis ON {0}.ci_id=c_cis.id 15 | AND {0}.`ci_id` IN ({1}) 16 | INNER JOIN c_attributes as attr ON attr.id = {0}.attr_id 17 | """ 18 | 19 | # {2}: value_table 20 | QUERY_CIS_BY_IDS = """ 21 | SELECT A.ci_id, 22 | A.type_id, 23 | A.attr_id, 24 | A.attr_name, 25 | A.attr_alias, 26 | A.value, 27 | A.value_type, 28 | A.is_list 29 | FROM 30 | ({1}) AS A {0} 31 | ORDER BY A.ci_id; 32 | """ 33 | 34 | FACET_QUERY1 = """ 35 | SELECT {0}.value, 36 | count({0}.ci_id) 37 | FROM {0} 38 | INNER JOIN c_attributes AS attr ON attr.id={0}.attr_id 39 | WHERE attr.name="{1}" 40 | GROUP BY {0}.ci_id; 41 | """ 42 | 43 | FACET_QUERY = """ 44 | SELECT {0}.value, 45 | count(distinct({0}.ci_id)) 46 | FROM {0} 47 | INNER JOIN ({1}) AS F ON F.ci_id={0}.ci_id 48 | WHERE {0}.attr_id={2:d} 49 | GROUP BY {0}.value 50 | """ 51 | 52 | QUERY_CI_BY_ATTR_NAME = """ 53 | SELECT {0}.ci_id 54 | FROM {0} 55 | WHERE {0}.attr_id={1:d} 56 | AND {0}.value {2} 57 | """ 58 | 59 | QUERY_CI_BY_TYPE = """ 60 | SELECT c_cis.id AS ci_id 61 | FROM c_cis 62 | WHERE c_cis.type_id in ({0}) 63 | """ 64 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/relation_type.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | from flask import abort 5 | 6 | from api.lib.cmdb.resp_format import ErrFormat 7 | from api.models.cmdb import RelationType 8 | 9 | 10 | class RelationTypeManager(object): 11 | cls = RelationType 12 | 13 | @staticmethod 14 | def get_all(): 15 | return RelationType.get_by(to_dict=False) 16 | 17 | @classmethod 18 | def get_names(cls): 19 | return [i.name for i in cls.get_all()] 20 | 21 | @classmethod 22 | def get_pairs(cls): 23 | return [(i.id, i.name) for i in cls.get_all()] 24 | 25 | @staticmethod 26 | def add(name): 27 | RelationType.get_by(name=name, first=True, to_dict=False) and abort( 28 | 400, ErrFormat.relation_type_exists.format(name)) 29 | 30 | return RelationType.create(name=name) 31 | 32 | @staticmethod 33 | def update(rel_id, name): 34 | existed = RelationType.get_by_id(rel_id) or abort( 35 | 404, ErrFormat.relation_type_not_found.format("id={}".format(rel_id))) 36 | 37 | return existed.update(name=name) 38 | 39 | @staticmethod 40 | def delete(rel_id): 41 | existed = RelationType.get_by_id(rel_id) or abort( 42 | 404, ErrFormat.relation_type_not_found.format("id={}".format(rel_id))) 43 | 44 | existed.soft_delete() 45 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/search/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | __all__ = ['ci', 'ci_relation', 'SearchError'] 4 | 5 | 6 | class SearchError(Exception): 7 | def __init__(self, v): 8 | self.v = v 9 | 10 | def __str__(self): 11 | return self.v 12 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/search/ci/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | __all__ = ['db', 'es', 'search'] 4 | 5 | from flask import current_app 6 | 7 | from api.lib.cmdb.const import RetKey 8 | from api.lib.cmdb.search.ci.db.search import Search as SearchFromDB 9 | from api.lib.cmdb.search.ci.es.search import Search as SearchFromES 10 | 11 | 12 | def search(query=None, 13 | fl=None, 14 | facet=None, 15 | page=1, 16 | ret_key=RetKey.NAME, 17 | count=1, 18 | sort=None, 19 | excludes=None, 20 | use_id_filter=False, 21 | use_ci_filter=True): 22 | if current_app.config.get("USE_ES"): 23 | s = SearchFromES(query, fl, facet, page, ret_key, count, sort) 24 | else: 25 | s = SearchFromDB(query, fl, facet, page, ret_key, count, sort, excludes=excludes, 26 | use_id_filter=use_id_filter, use_ci_filter=use_ci_filter) 27 | 28 | return s 29 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/search/ci/db/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/search/ci/es/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/cmdb/search/ci_relation/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/common_setting/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-api/api/lib/common_setting/__init__.py -------------------------------------------------------------------------------- /cmdb-api/api/lib/const.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from api.lib.utils import BaseEnum 4 | 5 | 6 | class PermEnum(BaseEnum): 7 | ADD = "create" 8 | UPDATE = "update" 9 | DELETE = "delete" 10 | READ = "read" 11 | EXECUTE = "execute" 12 | GRANT = "grant" 13 | ADMIN = "admin" 14 | 15 | 16 | class RoleEnum(BaseEnum): 17 | ADMIN = "OneOPS_Application_Admin" 18 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/exception.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | from werkzeug.exceptions import NotFound, Forbidden, BadRequest 5 | 6 | 7 | class CommitException(Exception): 8 | pass 9 | 10 | 11 | AbortException = (NotFound, Forbidden, BadRequest) 12 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/perm/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/perm/acl/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | from functools import wraps 5 | 6 | from flask import abort 7 | from flask import request 8 | 9 | from api.lib.perm.acl.cache import AppCache 10 | from api.lib.perm.acl.resp_format import ErrFormat 11 | 12 | 13 | def validate_app(func): 14 | @wraps(func) 15 | def wrapper(*args, **kwargs): 16 | if not request.headers.get('App-Access-Token', '').strip(): 17 | app_id = request.values.get('app_id') 18 | app = AppCache.get(app_id) 19 | if app is None: 20 | return abort(400, ErrFormat.app_not_found.format("id={}".format(app_id))) 21 | request.values['app_id'] = app.id 22 | 23 | return func(*args, **kwargs) 24 | 25 | return wrapper 26 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/perm/acl/const.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from api.lib.utils import BaseEnum 4 | 5 | ACL_QUEUE = "acl_async" 6 | 7 | 8 | class OperateType(BaseEnum): 9 | LOGIN = "0" 10 | READ = "1" 11 | UPDATE = "2" 12 | CREATE = "3" 13 | DELETE = "4" 14 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/perm/acl/record.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from api.models.acl import OperationRecord 4 | 5 | 6 | class OperateRecordCRUD(object): 7 | @staticmethod 8 | def search(page, page_size, **kwargs): 9 | query = OperationRecord.get_by(only_query=True) 10 | for k, v in kwargs.items(): 11 | if hasattr(OperationRecord, k) and v: 12 | query = query.filter(getattr(OperationRecord, k) == v) 13 | 14 | numfound = query.count() 15 | res = query.offset((page - 1) * page_size).limit(page_size) 16 | 17 | return numfound, res 18 | 19 | @staticmethod 20 | def add(app, rolename, operate, obj): 21 | OperationRecord.create(app=app, rolename=rolename, operate=operate, obj=obj) 22 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/perm/authentication/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/perm/authentication/oauth2/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from flask import current_app 4 | 5 | from . import routing 6 | 7 | 8 | class OAuth2(object): 9 | def __init__(self, app=None, url_prefix=None): 10 | self._app = app 11 | if app is not None: 12 | self.init_app(app, url_prefix) 13 | 14 | @staticmethod 15 | def init_app(app, url_prefix=None): 16 | # Configuration defaults 17 | app.config.setdefault('OAUTH2_GRANT_TYPE', 'authorization_code') 18 | app.config.setdefault('OAUTH2_RESPONSE_TYPE', 'code') 19 | app.config.setdefault('OAUTH2_AFTER_LOGIN', '/') 20 | 21 | app.config.setdefault('OIDC_GRANT_TYPE', 'authorization_code') 22 | app.config.setdefault('OIDC_RESPONSE_TYPE', 'code') 23 | app.config.setdefault('OIDC_AFTER_LOGIN', '/') 24 | 25 | # Register Blueprint 26 | app.register_blueprint(routing.blueprint, url_prefix=url_prefix) 27 | 28 | @property 29 | def app(self): 30 | return self._app or current_app 31 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/resp_format.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from flask_babel import lazy_gettext as _l 4 | 5 | 6 | class CommonErrFormat(object): 7 | unauthorized = _l("unauthorized") # 未认证 8 | unknown_error = _l("unknown error") # 未知错误 9 | 10 | invalid_request = _l("Illegal request") # 不合法的请求 11 | invalid_operation = _l("Invalid operation") # 无效的操作 12 | 13 | not_found = _l("does not exist") # 不存在 14 | 15 | circular_dependency_error = _l("There is a circular dependency!") # 存在循环依赖! 16 | 17 | unknown_search_error = _l("Unknown search error") # 未知搜索错误 18 | 19 | # json格式似乎不正确了, 请仔细确认一下! 20 | invalid_json = _l("The json format seems to be incorrect, please confirm carefully!") 21 | 22 | # 参数 {} 格式不正确, 格式必须是: yyyy-mm-dd HH:MM:SS 23 | datetime_argument_invalid = _l("The format of parameter {} is incorrect, the format must be: yyyy-mm-dd HH:MM:SS") 24 | 25 | argument_value_required = _l("The value of parameter {} cannot be empty!") # 参数 {} 的值不能为空! 26 | argument_required = _l("The request is missing parameters {}") # 请求缺少参数 {} 27 | argument_invalid = _l("Invalid value for parameter {}") # 参数 {} 的值无效 28 | argument_str_length_limit = _l("The length of parameter {} must be <= {}") # 参数 {} 的长度必须 <= {} 29 | 30 | role_required = _l("Role {} can only operate!") # 角色 {} 才能操作! 31 | user_not_found = _l("User {} does not exist") # 用户 {} 不存在 32 | no_permission = _l("For resource: {}, you do not have {} permission!") # 您没有资源: {} 的{}权限! 33 | no_permission2 = _l("You do not have permission to operate!") # 您没有操作权限! 34 | no_permission_only_owner = _l("Only the creator or administrator has permission!") # 只有创建人或者管理员才有权限! 35 | -------------------------------------------------------------------------------- /cmdb-api/api/lib/secrets/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/models/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | from .cmdb import * 5 | from .acl import * 6 | -------------------------------------------------------------------------------- /cmdb-api/api/tasks/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/translations/zh/LC_MESSAGES/messages.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-api/api/translations/zh/LC_MESSAGES/messages.mo -------------------------------------------------------------------------------- /cmdb-api/api/views/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | -------------------------------------------------------------------------------- /cmdb-api/api/views/acl/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/views/acl/audit.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from flask import request, abort 4 | 5 | from api.lib.perm.acl.audit import AuditCRUD 6 | from api.lib.utils import get_page 7 | from api.lib.utils import get_page_size 8 | from api.resource import APIView 9 | 10 | 11 | class AuditLogView(APIView): 12 | url_prefix = ("/audit_log/",) 13 | 14 | def get(self, name): 15 | page = get_page(request.values.get("page", 1)) 16 | page_size = get_page_size(request.values.get("page_size")) 17 | app_id = request.values.get('app_id') 18 | q = request.values.get('q') 19 | start = request.values.get('start') 20 | end = request.values.get('end') 21 | 22 | func_map = { 23 | 'permission': AuditCRUD.search_permission, 24 | 'role': AuditCRUD.search_role, 25 | 'trigger': AuditCRUD.search_trigger, 26 | 'resource': AuditCRUD.search_resource, 27 | 'login': AuditCRUD.search_login, 28 | } 29 | if name not in func_map: 30 | abort(400, f'wrong {name}, please use {func_map.keys()}') 31 | 32 | _func = func_map[name] 33 | 34 | data = _func(app_id, q, page, page_size, start, end) 35 | 36 | return self.jsonify( 37 | page=page, 38 | page_size=page_size, 39 | **data, 40 | ) 41 | -------------------------------------------------------------------------------- /cmdb-api/api/views/cmdb/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/views/cmdb/c_stats.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | from api.lib.cmdb.cache import CMDBCounterCache 5 | from api.resource import APIView 6 | 7 | 8 | class CMDBStatisticsView(APIView): 9 | url_prefix = "/statistics" 10 | 11 | def get(self): 12 | return self.jsonify(CMDBCounterCache.get()) 13 | -------------------------------------------------------------------------------- /cmdb-api/api/views/cmdb/dcim/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/views/cmdb/dcim/dcim_history.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from flask import request 4 | 5 | from api.lib.cmdb.dcim.history import OperateHistoryManager 6 | from api.lib.common_setting.decorator import perms_role_required 7 | from api.lib.common_setting.role_perm_base import CMDBApp 8 | from api.lib.utils import get_page 9 | from api.lib.utils import get_page_size 10 | from api.lib.utils import handle_arg_list 11 | from api.resource import APIView 12 | 13 | app_cli = CMDBApp() 14 | 15 | 16 | class DCIMOperateHistoryView(APIView): 17 | url_prefix = ("/dcim/history/operate",) 18 | 19 | @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.DCIM, 20 | app_cli.op.read, app_cli.admin_name) 21 | def get(self): 22 | page = get_page(request.values.pop("page", 1)) 23 | page_size = get_page_size(request.values.pop("page_size", None)) 24 | operate_type = handle_arg_list(request.values.pop('operate_type', [])) 25 | if operate_type: 26 | request.values["operate_type"] = operate_type 27 | 28 | numfound, result, id2ci, type2show_key = OperateHistoryManager.search(page, page_size, **request.values) 29 | 30 | return self.jsonify(numfound=numfound, result=result, id2ci=id2ci, type2show_key=type2show_key) 31 | -------------------------------------------------------------------------------- /cmdb-api/api/views/cmdb/dcim/idc.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from flask import request 4 | 5 | from api.lib.cmdb.dcim.idc import IDCManager 6 | from api.lib.common_setting.decorator import perms_role_required 7 | from api.lib.common_setting.role_perm_base import CMDBApp 8 | from api.resource import APIView 9 | 10 | app_cli = CMDBApp() 11 | 12 | 13 | class IDCView(APIView): 14 | url_prefix = ("/dcim/idc", "/dcim/idc/") 15 | 16 | @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.DCIM, 17 | app_cli.op.read, app_cli.admin_name) 18 | def post(self): 19 | parent_id = request.values.pop("parent_id") 20 | 21 | return self.jsonify(ci_id=IDCManager().add(parent_id, **request.values)) 22 | 23 | @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.DCIM, 24 | app_cli.op.read, app_cli.admin_name) 25 | def put(self, _id): 26 | IDCManager().update(_id, **request.values) 27 | 28 | return self.jsonify(ci_id=_id) 29 | 30 | @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.DCIM, 31 | app_cli.op.read, app_cli.admin_name) 32 | def delete(self, _id): 33 | IDCManager().delete(_id) 34 | 35 | return self.jsonify(ci_id=_id) 36 | -------------------------------------------------------------------------------- /cmdb-api/api/views/cmdb/dcim/region.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from flask import request 4 | 5 | from api.lib.cmdb.dcim.region import RegionManager 6 | from api.lib.common_setting.decorator import perms_role_required 7 | from api.lib.common_setting.role_perm_base import CMDBApp 8 | from api.resource import APIView 9 | 10 | app_cli = CMDBApp() 11 | 12 | 13 | class RegionView(APIView): 14 | url_prefix = ("/dcim/region", "/dcim/region/") 15 | 16 | @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.DCIM, 17 | app_cli.op.read, app_cli.admin_name) 18 | def post(self): 19 | return self.jsonify(ci_id=RegionManager().add(**request.values)) 20 | 21 | @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.DCIM, 22 | app_cli.op.read, app_cli.admin_name) 23 | def put(self, _id): 24 | RegionManager().update(_id, **request.values) 25 | 26 | return self.jsonify(ci_id=_id) 27 | 28 | @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.DCIM, 29 | app_cli.op.read, app_cli.admin_name) 30 | def delete(self, _id): 31 | RegionManager().delete(_id) 32 | 33 | return self.jsonify(ci_id=_id) 34 | -------------------------------------------------------------------------------- /cmdb-api/api/views/cmdb/dcim/server_room.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from flask import request 4 | 5 | from api.lib.cmdb.dcim.server_room import ServerRoomManager 6 | from api.lib.common_setting.decorator import perms_role_required 7 | from api.lib.common_setting.role_perm_base import CMDBApp 8 | from api.lib.decorator import args_required 9 | from api.resource import APIView 10 | 11 | app_cli = CMDBApp() 12 | 13 | 14 | class ServerRoomView(APIView): 15 | url_prefix = ("/dcim/server_room", "/dcim/server_room/", "/dcim/server_room//racks") 16 | 17 | def get(self, _id): 18 | q = request.values.get('q') 19 | counter, result = ServerRoomManager.get_racks(_id, q) 20 | 21 | return self.jsonify(counter=counter, result=result) 22 | 23 | @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.DCIM, 24 | app_cli.op.read, app_cli.admin_name) 25 | @args_required("parent_id") 26 | def post(self): 27 | parent_id = request.values.pop("parent_id") 28 | 29 | return self.jsonify(ci_id=ServerRoomManager().add(parent_id, **request.values)) 30 | 31 | @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.DCIM, 32 | app_cli.op.read, app_cli.admin_name) 33 | def put(self, _id): 34 | ServerRoomManager().update(_id, **request.values) 35 | 36 | return self.jsonify(ci_id=_id) 37 | 38 | @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.DCIM, 39 | app_cli.op.read, app_cli.admin_name) 40 | def delete(self, _id): 41 | ServerRoomManager().delete(_id) 42 | 43 | return self.jsonify(ci_id=_id) 44 | -------------------------------------------------------------------------------- /cmdb-api/api/views/cmdb/dcim/tree_view.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from api.lib.cmdb.dcim.tree_view import TreeViewManager 4 | from api.lib.common_setting.decorator import perms_role_required 5 | from api.lib.common_setting.role_perm_base import CMDBApp 6 | from api.resource import APIView 7 | 8 | app_cli = CMDBApp() 9 | 10 | 11 | class DCIMTreeView(APIView): 12 | url_prefix = "/dcim/tree_view" 13 | 14 | @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.DCIM, 15 | app_cli.op.read, app_cli.admin_name) 16 | def get(self): 17 | result, type2name = TreeViewManager.get() 18 | 19 | return self.jsonify(result=result, type2name=type2name) 20 | -------------------------------------------------------------------------------- /cmdb-api/api/views/cmdb/inner_secrets.py: -------------------------------------------------------------------------------- 1 | from flask import request 2 | 3 | from api.lib.perm.auth import auth_abandoned 4 | from api.lib.secrets.inner import KeyManage 5 | from api.lib.secrets.secrets import InnerKVManger 6 | from api.resource import APIView 7 | 8 | 9 | class InnerSecretUnSealView(APIView): 10 | url_prefix = "/secrets/unseal" 11 | 12 | @auth_abandoned 13 | def post(self): 14 | unseal_key = request.headers.get("Unseal-Token") 15 | res = KeyManage(backend=InnerKVManger()).unseal(unseal_key) 16 | return self.jsonify(**res) 17 | 18 | 19 | class InnerSecretSealView(APIView): 20 | url_prefix = "/secrets/seal" 21 | 22 | @auth_abandoned 23 | def post(self): 24 | unseal_key = request.headers.get("Inner-Token") 25 | res = KeyManage(backend=InnerKVManger()).seal(unseal_key) 26 | return self.jsonify(**res) 27 | 28 | 29 | class InnerSecretAutoSealView(APIView): 30 | url_prefix = "/secrets/auto_seal" 31 | 32 | @auth_abandoned 33 | def post(self): 34 | root_key = request.headers.get("Inner-Token") 35 | res = KeyManage(trigger=root_key, 36 | backend=InnerKVManger()).auto_unseal() 37 | return self.jsonify(**res) 38 | -------------------------------------------------------------------------------- /cmdb-api/api/views/cmdb/ipam/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/api/views/cmdb/ipam/address.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from flask import request 4 | 5 | from api.lib.cmdb.ipam.address import IpAddressManager 6 | from api.lib.common_setting.decorator import perms_role_required 7 | from api.lib.common_setting.role_perm_base import CMDBApp 8 | from api.lib.decorator import args_required 9 | from api.lib.utils import handle_arg_list 10 | from api.resource import APIView 11 | 12 | app_cli = CMDBApp() 13 | 14 | 15 | class IPAddressView(APIView): 16 | url_prefix = ("/ipam/address",) 17 | 18 | @args_required("parent_id") 19 | @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.IPAM, 20 | app_cli.op.read, app_cli.admin_name) 21 | def get(self): 22 | parent_id = request.args.get("parent_id") 23 | 24 | numfound, result = IpAddressManager.list_ip_address(parent_id) 25 | 26 | return self.jsonify(numfound=numfound, result=result) 27 | 28 | @args_required("ips") 29 | @args_required("assign_status", value_required=False) 30 | @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.IPAM, 31 | app_cli.op.read, app_cli.admin_name) 32 | def post(self): 33 | ips = handle_arg_list(request.values.pop("ips")) 34 | parent_id = request.values.pop("parent_id", None) 35 | cidr = request.values.pop("cidr", None) 36 | 37 | IpAddressManager().assign_ips(ips, parent_id, cidr, **request.values) 38 | 39 | return self.jsonify(code=200) 40 | -------------------------------------------------------------------------------- /cmdb-api/api/views/cmdb/ipam/ipam_stats.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | from flask import request 5 | 6 | from api.lib.cmdb.ipam.stats import Stats 7 | from api.lib.common_setting.decorator import perms_role_required 8 | from api.lib.common_setting.role_perm_base import CMDBApp 9 | from api.lib.decorator import args_required 10 | from api.resource import APIView 11 | 12 | app_cli = CMDBApp() 13 | 14 | 15 | class IPAMStatsView(APIView): 16 | url_prefix = '/ipam/stats' 17 | 18 | @args_required("parent_id") 19 | @perms_role_required(app_cli.app_name, app_cli.resource_type_name, app_cli.op.IPAM, 20 | app_cli.op.read, app_cli.admin_name) 21 | def get(self): 22 | parent_id = request.values.get("parent_id") 23 | 24 | return self.jsonify(Stats().summary(parent_id)) 25 | -------------------------------------------------------------------------------- /cmdb-api/api/views/common_setting/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-api/api/views/common_setting/__init__.py -------------------------------------------------------------------------------- /cmdb-api/api/views/common_setting/common_data.py: -------------------------------------------------------------------------------- 1 | from flask import request 2 | 3 | from api.lib.common_setting.common_data import CommonDataCRUD 4 | from api.resource import APIView 5 | 6 | prefix = '/data' 7 | 8 | 9 | class DataView(APIView): 10 | url_prefix = (f'{prefix}/',) 11 | 12 | def get(self, data_type): 13 | data_list = CommonDataCRUD.get_data_by_type(data_type) 14 | 15 | return self.jsonify(data_list) 16 | 17 | def post(self, data_type): 18 | params = request.json 19 | CommonDataCRUD.create_new_data(data_type, **params) 20 | 21 | return self.jsonify(params) 22 | 23 | 24 | class DataViewWithId(APIView): 25 | url_prefix = (f'{prefix}//',) 26 | 27 | def put(self, data_type, _id): 28 | params = request.json 29 | res = CommonDataCRUD.update_data(_id, **params) 30 | 31 | return self.jsonify(res.to_dict()) 32 | 33 | def delete(self, data_type, _id): 34 | CommonDataCRUD.delete(_id) 35 | return self.jsonify({}) 36 | -------------------------------------------------------------------------------- /cmdb-api/api/views/common_setting/company_info.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from flask import request 3 | 4 | from api.lib.common_setting.company_info import CompanyInfoCRUD 5 | from api.resource import APIView 6 | 7 | prefix = '/company' 8 | 9 | 10 | class CompanyInfoView(APIView): 11 | url_prefix = (f'{prefix}/info',) 12 | 13 | def get(self): 14 | return self.jsonify(CompanyInfoCRUD.get()) 15 | 16 | def post(self): 17 | data = { 18 | 'info': { 19 | **request.values 20 | } 21 | } 22 | info = CompanyInfoCRUD.get() 23 | if info: 24 | d = CompanyInfoCRUD.update(info.get('id'), **data) 25 | else: 26 | d = CompanyInfoCRUD.create(**data) 27 | res = d.to_dict() 28 | return self.jsonify(res) 29 | 30 | 31 | class CompanyInfoViewWithId(APIView): 32 | url_prefix = (f'{prefix}/info/',) 33 | 34 | def put(self, _id): 35 | data = { 36 | 'info': { 37 | **request.values 38 | } 39 | } 40 | d = CompanyInfoCRUD.update(_id, **data) 41 | res = d.to_dict() 42 | return self.jsonify(res) 43 | -------------------------------------------------------------------------------- /cmdb-api/api/views/entry.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | import os 4 | 5 | from flask import Blueprint 6 | from flask_restful import Api 7 | 8 | from api.resource import register_resources 9 | from .account import AuthWithKeyView 10 | from .account import LoginView 11 | from .account import LogoutView 12 | 13 | HERE = os.path.abspath(os.path.dirname(__file__)) 14 | 15 | # account 16 | blueprint_account = Blueprint('account_api', __name__, url_prefix='/api') 17 | account_rest = Api(blueprint_account) 18 | account_rest.add_resource(LoginView, LoginView.url_prefix) 19 | account_rest.add_resource(LogoutView, LogoutView.url_prefix) 20 | account_rest.add_resource(AuthWithKeyView, AuthWithKeyView.url_prefix) 21 | 22 | # cmdb 23 | blueprint_cmdb_v01 = Blueprint('cmdb_api_v01', __name__, url_prefix='/api/v0.1') 24 | rest = Api(blueprint_cmdb_v01) 25 | register_resources(os.path.join(HERE, "cmdb"), rest) 26 | 27 | # acl 28 | blueprint_acl_v1 = Blueprint('acl_api_v1', __name__, url_prefix='/api/v1/acl') 29 | rest = Api(blueprint_acl_v1) 30 | register_resources(os.path.join(HERE, "acl"), rest) 31 | 32 | # common_setting 33 | blueprint_cs_v1 = Blueprint('common_setting_api_v1', __name__, url_prefix='/api/common-setting/v1') 34 | rest = Api(blueprint_cs_v1) 35 | register_resources(os.path.join(HERE, "common_setting"), rest) 36 | -------------------------------------------------------------------------------- /cmdb-api/autoapp.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """Create an application instance.""" 4 | 5 | from api.app import create_app 6 | 7 | app = create_app() 8 | -------------------------------------------------------------------------------- /cmdb-api/babel.cfg: -------------------------------------------------------------------------------- 1 | [python: api/**.py] 2 | -------------------------------------------------------------------------------- /cmdb-api/celery_worker.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from api.app import create_app 4 | from api.extensions import celery 5 | 6 | # celery -A celery_worker.celery worker -l DEBUG -E -Q xxxx 7 | 8 | app = create_app() 9 | app.app_context().push() 10 | -------------------------------------------------------------------------------- /cmdb-api/logs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-api/logs/.gitkeep -------------------------------------------------------------------------------- /cmdb-api/migrations/README: -------------------------------------------------------------------------------- 1 | Generic single-database configuration. -------------------------------------------------------------------------------- /cmdb-api/migrations/alembic.ini: -------------------------------------------------------------------------------- 1 | # A generic, single database configuration. 2 | 3 | [alembic] 4 | # template used to generate migration files 5 | # file_template = %%(rev)s_%%(slug)s 6 | 7 | # set to 'true' to run the environment during 8 | # the 'revision' command, regardless of autogenerate 9 | # revision_environment = false 10 | 11 | 12 | # Logging configuration 13 | [loggers] 14 | keys = root,sqlalchemy,alembic 15 | 16 | [handlers] 17 | keys = console 18 | 19 | [formatters] 20 | keys = generic 21 | 22 | [logger_root] 23 | level = WARN 24 | handlers = console 25 | qualname = 26 | 27 | [logger_sqlalchemy] 28 | level = WARN 29 | handlers = 30 | qualname = sqlalchemy.engine 31 | 32 | [logger_alembic] 33 | level = INFO 34 | handlers = 35 | qualname = alembic 36 | 37 | [handler_console] 38 | class = StreamHandler 39 | args = (sys.stderr,) 40 | level = NOTSET 41 | formatter = generic 42 | 43 | [formatter_generic] 44 | format = %(levelname)-5.5s [%(name)s] %(message)s 45 | datefmt = %H:%M:%S 46 | -------------------------------------------------------------------------------- /cmdb-api/migrations/script.py.mako: -------------------------------------------------------------------------------- 1 | """${message} 2 | 3 | Revision ID: ${up_revision} 4 | Revises: ${down_revision | comma,n} 5 | Create Date: ${create_date} 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | ${imports if imports else ""} 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = ${repr(up_revision)} 14 | down_revision = ${repr(down_revision)} 15 | branch_labels = ${repr(branch_labels)} 16 | depends_on = ${repr(depends_on)} 17 | 18 | 19 | def upgrade(): 20 | ${upgrades if upgrades else "pass"} 21 | 22 | 23 | def downgrade(): 24 | ${downgrades if downgrades else "pass"} 25 | -------------------------------------------------------------------------------- /cmdb-api/requirements.txt: -------------------------------------------------------------------------------- 1 | -i https://mirrors.aliyun.com/pypi/simple 2 | alembic==1.7.7 3 | bs4==0.0.1 4 | celery==5.3.1 5 | celery-once==3.0.1 6 | click==8.1.3 7 | elasticsearch==7.17.9 8 | email-validator==1.3.1 9 | environs==4.2.0 10 | flasgger==0.9.5 11 | Flask==2.2.5 12 | Flask-Bcrypt==1.0.1 13 | flask-babel==4.0.0 14 | Flask-Caching==2.0.2 15 | Flask-Cors==4.0.0 16 | Flask-Login>=0.6.2 17 | Flask-Migrate==2.5.2 18 | Flask-RESTful==0.3.10 19 | Flask-SQLAlchemy==3.0.5 20 | future==0.18.3 21 | gunicorn==21.0.1 22 | hvac==2.0.0 23 | itsdangerous==2.1.2 24 | Jinja2==3.1.2 25 | jinja2schema==0.1.4 26 | jsonschema==4.18.0 27 | kombu>=5.3.1 28 | Mako==1.2.4 29 | MarkupSafe==2.1.3 30 | marshmallow==2.20.2 31 | more-itertools==5.0.0 32 | msgpack-python==0.5.6 33 | Pillow>=10.0.1 34 | pycryptodome==3.12.0 35 | cryptography>=41.0.2 36 | PyJWT==2.4.0 37 | PyMySQL==1.1.0 38 | ldap3==2.9.1 39 | PyYAML==6.0.1 40 | redis==4.6.0 41 | python-redis-lock==4.0.0 42 | requests==2.31.0 43 | requests_oauthlib==1.3.1 44 | markdownify==0.11.6 45 | six==1.16.0 46 | SQLAlchemy==1.4.49 47 | supervisor==4.0.3 48 | timeout-decorator==0.5.0 49 | toposort==1.10 50 | treelib==1.6.1 51 | Werkzeug==2.2.3 52 | WTForms==3.0.0 53 | shamir~=17.12.0 54 | pycryptodomex>=3.19.0 55 | colorama>=0.4.6 56 | lz4>=4.3.2 57 | python-magic==0.4.27 58 | jsonpath==0.82.2 59 | networkx>=3.1 60 | ipaddress>=1.0.23 61 | ruff==0.8.3 62 | -------------------------------------------------------------------------------- /cmdb-api/tests/__init__.py: -------------------------------------------------------------------------------- 1 | """Tests for the app.""" 2 | -------------------------------------------------------------------------------- /cmdb-api/tests/conftest.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """Defines fixtures available to all tests.""" 3 | 4 | import pytest 5 | from webtest import TestApp 6 | 7 | from api.app import create_app 8 | 9 | 10 | @pytest.fixture 11 | def app(): 12 | """Create application for the tests.""" 13 | _app = create_app("tests.settings") 14 | ctx = _app.test_request_context() 15 | ctx.push() 16 | yield _app 17 | 18 | ctx.pop() 19 | 20 | 21 | @pytest.fixture 22 | def testapp(app): 23 | """Create Webtest app.""" 24 | return TestApp(app) 25 | -------------------------------------------------------------------------------- /cmdb-api/tests/test_cmdb_attribute.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/tests/test_cmdb_ci.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | class TestCI: 5 | 6 | def test_ci_search_only_type_query(self, app): 7 | with app.test_client() as c: 8 | rv = c.get('/api/v0.1/ci/s?q=_type:server', json={}) 9 | json_data = rv.get_json() 10 | assert type(json_data.get("result")) is list 11 | -------------------------------------------------------------------------------- /cmdb-api/tests/test_cmdb_ci_realtion.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/tests/test_cmdb_ci_type.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/tests/test_cmdb_ci_type_relation.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/tests/test_cmdb_history.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/tests/test_cmdb_preference.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-api/tests/test_cmdb_relation_type.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | -------------------------------------------------------------------------------- /cmdb-ui/.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset=utf-8 3 | end_of_line=lf 4 | insert_final_newline=false 5 | indent_style=space 6 | indent_size=2 7 | 8 | [{*.ng,*.sht,*.html,*.shtm,*.shtml,*.htm}] 9 | indent_style=space 10 | indent_size=2 11 | 12 | [{*.jhm,*.xslt,*.xul,*.rng,*.xsl,*.xsd,*.ant,*.tld,*.fxml,*.jrxml,*.xml,*.jnlp,*.wsdl}] 13 | indent_style=space 14 | indent_size=2 15 | 16 | [{.babelrc,.stylelintrc,jest.config,.eslintrc,.prettierrc,*.json,*.jsb3,*.jsb2,*.bowerrc}] 17 | indent_style=space 18 | indent_size=2 19 | 20 | [*.svg] 21 | indent_style=space 22 | indent_size=2 23 | 24 | [*.js.map] 25 | indent_style=space 26 | indent_size=2 27 | 28 | [*.less] 29 | indent_style=space 30 | indent_size=2 31 | 32 | [*.vue] 33 | indent_style=space 34 | indent_size=2 35 | 36 | [{.analysis_options,*.yml,*.yaml}] 37 | indent_style=space 38 | indent_size=2 39 | 40 | -------------------------------------------------------------------------------- /cmdb-ui/.env: -------------------------------------------------------------------------------- 1 | NODE_ENV=production 2 | VUE_APP_PREVIEW=false 3 | VUE_APP_API_BASE_URL=http://127.0.0.1:5000/api 4 | VUE_APP_BUILD_PACKAGES="ticket,calendar,acl" 5 | VUE_APP_IS_OUTER=true 6 | VUE_APP_IS_OPEN_SOURCE=true 7 | -------------------------------------------------------------------------------- /cmdb-ui/.env.preview: -------------------------------------------------------------------------------- 1 | NODE_ENV=production 2 | VUE_APP_PREVIEW=true 3 | VUE_APP_API_BASE_URL=/api -------------------------------------------------------------------------------- /cmdb-ui/.eslintignore: -------------------------------------------------------------------------------- 1 | /public/iconfont 2 | /src/modules/cmdb/3rd -------------------------------------------------------------------------------- /cmdb-ui/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "semi": false, 4 | "singleQuote": true, 5 | "trailingComma": "es5" 6 | } 7 | -------------------------------------------------------------------------------- /cmdb-ui/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 10.15.0 4 | cache: yarn 5 | script: 6 | - yarn 7 | - yarn run lint --no-fix && yarn run build 8 | -------------------------------------------------------------------------------- /cmdb-ui/babel.config.js: -------------------------------------------------------------------------------- 1 | const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV) 2 | 3 | const plugins = ['@babel/plugin-syntax-import-meta', '@babel/plugin-proposal-optional-chaining', '@babel/plugin-proposal-nullish-coalescing-operator'] 4 | if (IS_PROD) { 5 | plugins.push('transform-remove-console') 6 | } 7 | 8 | // lazy load ant-design-vue 9 | // if your use import on Demand, Use this code 10 | // plugins.push(['import', { 11 | // 'libraryName': 'ant-design-vue', 12 | // 'libraryDirectory': 'es', 13 | // 'style': true // `style: true` 会加载 less 文件 14 | // }]) 15 | 16 | module.exports = { 17 | presets: [ 18 | '@vue/cli-plugin-babel/preset', 19 | [ 20 | '@babel/preset-env', 21 | { 22 | 'useBuiltIns': 'entry', 23 | 'corejs': 3 24 | } 25 | ] 26 | ], 27 | plugins 28 | } 29 | -------------------------------------------------------------------------------- /cmdb-ui/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleFileExtensions: [ 3 | 'js', 4 | 'jsx', 5 | 'json', 6 | 'vue' 7 | ], 8 | transform: { 9 | '^.+\\.vue$': 'vue-jest', 10 | '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub', 11 | '^.+\\.jsx?$': 'babel-jest' 12 | }, 13 | moduleNameMapper: { 14 | '^@/(.*)$': '/src/$1' 15 | }, 16 | snapshotSerializers: [ 17 | 'jest-serializer-vue' 18 | ], 19 | testMatch: [ 20 | '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)' 21 | ], 22 | testURL: 'http://localhost/' 23 | } 24 | -------------------------------------------------------------------------------- /cmdb-ui/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": ["src/*"] 7 | } 8 | }, 9 | "exclude": ["node_modules", "dist"], 10 | "include": ["src/*"] 11 | } 12 | -------------------------------------------------------------------------------- /cmdb-ui/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /cmdb-ui/public/iconfont/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/public/iconfont/iconfont.ttf -------------------------------------------------------------------------------- /cmdb-ui/public/iconfont/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/public/iconfont/iconfont.woff -------------------------------------------------------------------------------- /cmdb-ui/public/iconfont/iconfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/public/iconfont/iconfont.woff2 -------------------------------------------------------------------------------- /cmdb-ui/public/loading/loading.css: -------------------------------------------------------------------------------- 1 | #preloadingAnimation{position:fixed;left:0;top:0;height:100%;width:100%;background:#ffffff;user-select:none;z-index: 9999;overflow: hidden}.lds-roller{display:inline-block;position:relative;left:50%;top:50%;transform:translate(-50%,-50%);width:64px;height:64px;}.lds-roller div{animation:lds-roller 1.2s cubic-bezier(0.5,0,0.5,1) infinite;transform-origin:32px 32px;}.lds-roller div:after{content:" ";display:block;position:absolute;width:6px;height:6px;border-radius:50%;background:#13c2c2;margin:-3px 0 0 -3px;}.lds-roller div:nth-child(1){animation-delay:-0.036s;}.lds-roller div:nth-child(1):after{top:50px;left:50px;}.lds-roller div:nth-child(2){animation-delay:-0.072s;}.lds-roller div:nth-child(2):after{top:54px;left:45px;}.lds-roller div:nth-child(3){animation-delay:-0.108s;}.lds-roller div:nth-child(3):after{top:57px;left:39px;}.lds-roller div:nth-child(4){animation-delay:-0.144s;}.lds-roller div:nth-child(4):after{top:58px;left:32px;}.lds-roller div:nth-child(5){animation-delay:-0.18s;}.lds-roller div:nth-child(5):after{top:57px;left:25px;}.lds-roller div:nth-child(6){animation-delay:-0.216s;}.lds-roller div:nth-child(6):after{top:54px;left:19px;}.lds-roller div:nth-child(7){animation-delay:-0.252s;}.lds-roller div:nth-child(7):after{top:50px;left:14px;}.lds-roller div:nth-child(8){animation-delay:-0.288s;}.lds-roller div:nth-child(8):after{top:45px;left:10px;}#preloadingAnimation .load-tips{color: #13c2c2;font-size:2rem;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin-top:80px;text-align:center;width:400px;height:64px;} @keyframes lds-roller{0%{transform:rotate(0deg);} 100%{transform:rotate(360deg);}} -------------------------------------------------------------------------------- /cmdb-ui/public/loading/loading.html: -------------------------------------------------------------------------------- 1 |
Loading
-------------------------------------------------------------------------------- /cmdb-ui/public/loading/option2/loading.css: -------------------------------------------------------------------------------- 1 | .preloading-animate{background:#ffffff;width:100%;height:100%;position:fixed;left:0;top:0;z-index:299;}.preloading-animate .preloading-wrapper{position:absolute;width:5rem;height:5rem;left:50%;top:50%;transform:translate(-50%,-50%);}.preloading-animate .preloading-wrapper .preloading-balls{font-size:5rem;} -------------------------------------------------------------------------------- /cmdb-ui/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/public/logo.png -------------------------------------------------------------------------------- /cmdb-ui/src/api/auth.js: -------------------------------------------------------------------------------- 1 | import { axios } from '@/utils/request' 2 | 3 | export function getAuthData(data_type) { 4 | return axios({ 5 | url: `/common-setting/v1/auth_config/${data_type}`, 6 | method: 'get', 7 | }) 8 | } 9 | 10 | export function postAuthData(data_type, data) { 11 | return axios({ 12 | url: `/common-setting/v1/auth_config/${data_type}`, 13 | method: 'post', 14 | data, 15 | }) 16 | } 17 | 18 | export function putAuthData(data_type, id, data) { 19 | return axios({ 20 | url: `/common-setting/v1/auth_config/${data_type}/${id}`, 21 | method: 'put', 22 | data, 23 | }) 24 | } 25 | 26 | export function getAuthDataEnable() { 27 | return axios({ 28 | url: `/common-setting/v1/auth_config/enable_list`, 29 | method: 'get', 30 | }) 31 | } 32 | 33 | export function testLDAP(data) { 34 | return axios({ 35 | url: `/common-setting/v1/auth_config/LDAP/test`, 36 | method: 'post', 37 | data, 38 | }) 39 | } 40 | -------------------------------------------------------------------------------- /cmdb-ui/src/api/cmdb.js: -------------------------------------------------------------------------------- 1 | import { axios } from '@/utils/request' 2 | 3 | export function searchCI(params, isShowMessage = true) { 4 | return axios({ 5 | url: `/v0.1/ci/s`, 6 | method: 'GET', 7 | params: params, 8 | isShowMessage 9 | }) 10 | } 11 | 12 | export function getCIType(CITypeName, parameter) { 13 | return axios({ 14 | url: `/v0.1/ci_types/${CITypeName}`, 15 | method: 'GET', 16 | params: parameter 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /cmdb-ui/src/api/file.js: -------------------------------------------------------------------------------- 1 | import { axios } from '@/utils/request' 2 | 3 | export function postImageFile(parameter) { 4 | return axios({ 5 | url: '/common-setting/v1/file', 6 | method: 'post', 7 | data: parameter, 8 | }) 9 | } 10 | 11 | export function getFileData(data_type) { 12 | return axios({ 13 | url: `/common-setting/v1/data/${data_type}`, 14 | method: 'get', 15 | }) 16 | } 17 | 18 | export function addFileData(data_type, data) { 19 | return axios({ 20 | url: `/common-setting/v1/data/${data_type}`, 21 | method: 'post', 22 | data, 23 | }) 24 | } 25 | 26 | export function deleteFileData(data_type, id) { 27 | return axios({ 28 | url: `/common-setting/v1/data/${data_type}/${id}`, 29 | method: 'delete', 30 | }) 31 | } 32 | -------------------------------------------------------------------------------- /cmdb-ui/src/api/index.js: -------------------------------------------------------------------------------- 1 | const api = { 2 | Login: '/v1/acl/login', 3 | Logout: '/v1/acl/logout', 4 | ForgePassword: '/auth/forge-password', 5 | Register: '/auth/register', 6 | twoStepCode: '/auth/2step-code', 7 | SendSms: '/account/sms', 8 | SendSmsErr: '/account/sms_err', 9 | // get my info 10 | // UserInfo: '/v1/perms/user/info' 11 | UserInfo: process.env.VUE_APP_IS_OUTER === 'false' ? '/v1/perms/user/info' : '/v1/acl/users/info', 12 | } 13 | export default api 14 | -------------------------------------------------------------------------------- /cmdb-ui/src/api/login.js: -------------------------------------------------------------------------------- 1 | import api from './index' 2 | import { axios } from '@/utils/request' 3 | /** 4 | * login func 5 | * parameter: { 6 | * username: '', 7 | * password: '', 8 | * remember_me: true, 9 | * captcha: '12345' 10 | * } 11 | * @param parameter 12 | * @returns {*} 13 | */ 14 | export function login(data, auth_type) { 15 | if (auth_type) { 16 | localStorage.setItem('ops_auth_type', auth_type) 17 | window.location.href = `/api/${auth_type.toLowerCase()}/login` 18 | } else { 19 | return axios({ 20 | url: api.Login, 21 | method: 'POST', 22 | data: data 23 | }) 24 | } 25 | } 26 | 27 | export function getSmsCaptcha(parameter) { 28 | return axios({ 29 | url: api.SendSms, 30 | method: 'post', 31 | data: parameter 32 | }) 33 | } 34 | 35 | export function getInfo() { 36 | return axios({ 37 | url: api.UserInfo, 38 | method: 'get', 39 | headers: { 40 | 'Content-Type': 'application/json;charset=UTF-8' 41 | } 42 | }) 43 | } 44 | 45 | export function logout() { 46 | const auth_type = localStorage.getItem('ops_auth_type') 47 | localStorage.clear() 48 | return axios({ 49 | url: auth_type ? `/${auth_type.toLowerCase()}/logout` : api.Logout, 50 | method: auth_type ? 'get' : 'post', 51 | headers: { 52 | 'Content-Type': 'application/json;charset=UTF-8' 53 | } 54 | }) 55 | } 56 | 57 | /** 58 | * get user 2step code open? 59 | * @param parameter {*} 60 | */ 61 | export function get2step(parameter) { 62 | return axios({ 63 | url: api.twoStepCode, 64 | method: 'post', 65 | data: parameter 66 | }) 67 | } 68 | 69 | export function getAllUsers(params) { 70 | return axios({ 71 | url: '/v1/acl/users', 72 | method: 'GET', 73 | params 74 | }) 75 | } 76 | -------------------------------------------------------------------------------- /cmdb-ui/src/api/message.js: -------------------------------------------------------------------------------- 1 | import { axios } from '@/utils/request' 2 | 3 | export const getNoticeApps = () => { 4 | return axios({ 5 | url: `/common-setting/v1/message/apps`, 6 | method: 'get', 7 | }) 8 | } 9 | 10 | export const getNoticeCategoriesByApp = (app_name) => { 11 | return axios({ 12 | url: `/common-setting/v1/message/${app_name}/categories`, 13 | method: 'get', 14 | }) 15 | } 16 | 17 | export const getMessage = (params) => { 18 | return axios({ 19 | url: `/common-setting/v1/message`, 20 | method: 'get', 21 | params 22 | }) 23 | } 24 | 25 | export const postMessage = (data) => { 26 | return axios({ 27 | url: `/common-setting/v1/message`, 28 | method: 'post', 29 | data 30 | }) 31 | } 32 | 33 | export const updateMessage = (id, data) => { 34 | return axios({ 35 | url: `/common-setting/v1/message/${id}`, 36 | method: 'put', 37 | data 38 | }) 39 | } 40 | 41 | export const getUnreadMessageCount = (params) => { 42 | return axios({ 43 | url: `/common-setting/v1/message/unread`, 44 | method: 'get', 45 | params 46 | }) 47 | } 48 | 49 | export const batchUpdateMessage = (data) => { 50 | return axios({ 51 | url: `/common-setting/v1/message/batch`, 52 | method: 'post', 53 | data 54 | }) 55 | } 56 | -------------------------------------------------------------------------------- /cmdb-ui/src/api/noticeSetting.js: -------------------------------------------------------------------------------- 1 | import { axios } from '@/utils/request' 2 | 3 | export function sendTestEmail(receive_address, data) { 4 | return axios({ 5 | url: `/common-setting/v1/notice_config/send_test_email?receive_address=${receive_address}`, 6 | method: 'post', 7 | data 8 | }) 9 | } 10 | 11 | export const getNoticeConfigByPlatform = (platform) => { 12 | return axios({ 13 | url: '/common-setting/v1/notice_config', 14 | method: 'get', 15 | params: { ...platform }, 16 | }) 17 | } 18 | 19 | export const postNoticeConfigByPlatform = (data) => { 20 | return axios({ 21 | url: '/common-setting/v1/notice_config', 22 | method: 'post', 23 | data 24 | }) 25 | } 26 | 27 | export const putNoticeConfigByPlatform = (id, info) => { 28 | return axios({ 29 | url: `/common-setting/v1/notice_config/${id}`, 30 | method: 'put', 31 | data: info 32 | }) 33 | } 34 | 35 | export const getNoticeConfigAppBot = () => { 36 | return axios({ 37 | url: `/common-setting/v1/notice_config/app_bot`, 38 | method: 'get', 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /cmdb-ui/src/assets/data_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/assets/data_empty.png -------------------------------------------------------------------------------- /cmdb-ui/src/assets/file_upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/assets/file_upload.png -------------------------------------------------------------------------------- /cmdb-ui/src/assets/icon-bg-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/assets/icon-bg-selected.png -------------------------------------------------------------------------------- /cmdb-ui/src/assets/icon-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/assets/icon-bg.png -------------------------------------------------------------------------------- /cmdb-ui/src/assets/icons/ops-move-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cmdb-ui/src/assets/icons/top_acl.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cmdb-ui/src/assets/icons/top_agent.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cmdb-ui/src/assets/login_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/assets/login_bg.png -------------------------------------------------------------------------------- /cmdb-ui/src/assets/login_img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/assets/login_img.png -------------------------------------------------------------------------------- /cmdb-ui/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/assets/logo.png -------------------------------------------------------------------------------- /cmdb-ui/src/assets/logo_VECMDB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/assets/logo_VECMDB.png -------------------------------------------------------------------------------- /cmdb-ui/src/assets/ops_logout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/assets/ops_logout.png -------------------------------------------------------------------------------- /cmdb-ui/src/assets/sidebar_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/assets/sidebar_background.png -------------------------------------------------------------------------------- /cmdb-ui/src/assets/sidebar_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/assets/sidebar_selected.png -------------------------------------------------------------------------------- /cmdb-ui/src/bus/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | export default new Vue() 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/CMDBExprDrawer/index.js: -------------------------------------------------------------------------------- 1 | import CMDBExprDrawer from './index.vue' 2 | export default CMDBExprDrawer 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/CMDBExprDrawer/index.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/CardTitle/CardTitle.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 25 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/CardTitle/index.js: -------------------------------------------------------------------------------- 1 | import CardTitle from './CardTitle' 2 | export default CardTitle 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/Crontab/index.js: -------------------------------------------------------------------------------- 1 | import Vcrontab from './Crontab.vue' 2 | export default Vcrontab 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/CustomCodeMirror/index.js: -------------------------------------------------------------------------------- 1 | import CusotomCodeMirror from './index.vue' 2 | export default CusotomCodeMirror 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/CustomDrawer/index.js: -------------------------------------------------------------------------------- 1 | import CustomDrawer from './CustomDrawer' 2 | export default CustomDrawer 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/CustomIconSelect/index.js: -------------------------------------------------------------------------------- 1 | import CustomIconSelect from './index.vue' 2 | export default CustomIconSelect 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/CustomRadio/CustomRadio.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 40 | 41 | 55 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/CustomRadio/index.js: -------------------------------------------------------------------------------- 1 | import CustomRadio from './CustomRadio' 2 | export default CustomRadio 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/CustomTransfer/index.js: -------------------------------------------------------------------------------- 1 | import CustomTransfer from './CustomTransfer' 2 | export default CustomTransfer 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/EmployeeTransfer/index.js: -------------------------------------------------------------------------------- 1 | import EmployeeTransfer from './index.vue' 2 | export default EmployeeTransfer 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/Exception/index.js: -------------------------------------------------------------------------------- 1 | import ExceptionPage from './ExceptionPage.vue' 2 | export default ExceptionPage 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/Exception/type.js: -------------------------------------------------------------------------------- 1 | const types = { 2 | 403: { 3 | img: 'https://gw.alipayobjects.com/zos/rmsportal/wZcnGqRDyhPOEYFcZDnb.svg', 4 | title: '403', 5 | desc: '抱歉,你无权访问该页面' 6 | }, 7 | 404: { 8 | img: 'https://gw.alipayobjects.com/zos/rmsportal/KpnpchXsobRgLElEozzI.svg', 9 | title: '404', 10 | desc: '抱歉,你访问的页面不存在或仍在开发中' 11 | }, 12 | 500: { 13 | img: 'https://gw.alipayobjects.com/zos/rmsportal/RVRUAYdCGeYNBWoKiIwB.svg', 14 | title: '500', 15 | desc: '抱歉,服务器出错了' 16 | } 17 | } 18 | 19 | export default types 20 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/GlobalFooter/GlobalFooter.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 31 | 32 | 59 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/GlobalFooter/index.js: -------------------------------------------------------------------------------- 1 | import GlobalFooter from './GlobalFooter' 2 | export default GlobalFooter 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/GlobalHeader/index.js: -------------------------------------------------------------------------------- 1 | import GlobalHeader from './GlobalHeader' 2 | export default GlobalHeader 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/Menu/SideMenu.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 68 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/Menu/index.js: -------------------------------------------------------------------------------- 1 | import SMenu from './menu' 2 | export default SMenu 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/Menu/index.module.less: -------------------------------------------------------------------------------- 1 | .cmdb-side-menu-search { 2 | background-color: #FFFFFF !important; 3 | cursor: auto !important; 4 | 5 | :global { 6 | .ant-input-affix-wrapper { 7 | max-width: 170px !important; 8 | width: 170px; 9 | border-radius: 30px; 10 | } 11 | 12 | .ant-input { 13 | box-shadow: none; 14 | height: 30px; 15 | line-height: 30px; 16 | border-radius: 30px; 17 | 18 | &:focus { 19 | border: solid 1px #B1C9FF; 20 | } 21 | } 22 | 23 | .cmdb-side-menu-search-focused { 24 | .ant-input { 25 | border: solid 1px #B1C9FF; 26 | } 27 | } 28 | 29 | .ant-input-suffix { 30 | right: 0px !important; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/MonitorNodeSetting/index.js: -------------------------------------------------------------------------------- 1 | import MonitorNodeSetting from './index.vue' 2 | export default MonitorNodeSetting 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/MultiTab/index.js: -------------------------------------------------------------------------------- 1 | import MultiTab from './MultiTab' 2 | import './index.less' 3 | 4 | export default MultiTab 5 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/MultiTab/index.less: -------------------------------------------------------------------------------- 1 | @import '../index'; 2 | 3 | @multi-tab-prefix-cls: ~"@{ant-pro-prefix}-multi-tab"; 4 | @multi-tab-wrapper-prefix-cls: ~"@{ant-pro-prefix}-multi-tab-wrapper"; 5 | 6 | /* 7 | .topmenu .@{multi-tab-prefix-cls} { 8 | max-width: 1200px; 9 | margin: -23px auto 24px auto; 10 | } 11 | */ 12 | .@{multi-tab-prefix-cls} { 13 | margin: -23px -24px 24px -24px; 14 | background: #fff; 15 | } 16 | 17 | .topmenu .@{multi-tab-wrapper-prefix-cls} { 18 | max-width: 1200px; 19 | margin: 0 auto; 20 | } 21 | 22 | .topmenu.content-width-Fluid .@{multi-tab-wrapper-prefix-cls} { 23 | max-width: 100%; 24 | margin: 0 auto; 25 | } 26 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/OpsTable/index.js: -------------------------------------------------------------------------------- 1 | import OpsTable from './index.vue' 2 | export default OpsTable 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/PageHeader/index.js: -------------------------------------------------------------------------------- 1 | import PageHeader from './PageHeader' 2 | export default PageHeader 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/PageLoading/index.jsx: -------------------------------------------------------------------------------- 1 | import { Spin } from 'ant-design-vue' 2 | 3 | export default { 4 | name: 'PageLoading', 5 | render () { 6 | return (
7 | 8 |
) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/Pager/index.js: -------------------------------------------------------------------------------- 1 | import Pager from './index.vue' 2 | export default Pager 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/RegexSelect/index.js: -------------------------------------------------------------------------------- 1 | import RegexSelect from './regexSelect.vue' 2 | export default RegexSelect 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/Result/index.js: -------------------------------------------------------------------------------- 1 | import Result from './Result.vue' 2 | export default Result 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/RoleTransfer/index.js: -------------------------------------------------------------------------------- 1 | import RolesTransfer from './index.vue' 2 | export default RolesTransfer 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/SettingDrawer/SettingItem.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 24 | 25 | 39 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/SettingDrawer/index.js: -------------------------------------------------------------------------------- 1 | import SettingDrawer from './SettingDrawer' 2 | export default SettingDrawer 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/SettingDrawer/themeColor.js: -------------------------------------------------------------------------------- 1 | import client from 'webpack-theme-color-replacer/client' 2 | import generate from '@ant-design/colors/lib/generate' 3 | 4 | export default { 5 | getAntdSerials (color) { 6 | // 淡化(即less的tint) 7 | const lightens = new Array(9).fill().map((t, i) => { 8 | return client.varyColor.lighten(color, i / 10) 9 | }) 10 | // colorPalette变换得到颜色值 11 | const colorPalettes = generate(color) 12 | return lightens.concat(colorPalettes) 13 | }, 14 | changeColor (newColor) { 15 | var options = { 16 | newColors: this.getAntdSerials(newColor), // new colors array, one-to-one corresponde with `matchColors` 17 | changeUrl (cssUrl) { 18 | return `/${cssUrl}` // while router is not `hash` mode, it needs absolute path 19 | } 20 | } 21 | return client.changer.changeColor(options, Promise) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/SidebarList/index.js: -------------------------------------------------------------------------------- 1 | import SidebarList from './SidebarList' 2 | export default SidebarList 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/SplitPane/index.js: -------------------------------------------------------------------------------- 1 | import SplitPane from './SplitPane' 2 | export default SplitPane 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/SplitPane/index.less: -------------------------------------------------------------------------------- 1 | .split-pane { 2 | height: 100%; 3 | display: flex; 4 | } 5 | 6 | .split-pane .pane-two { 7 | flex: 1; 8 | } 9 | 10 | .split-pane .pane-trigger { 11 | user-select: none; 12 | } 13 | 14 | .split-pane.row .pane-one { 15 | width: 20%; 16 | height: 100%; 17 | // overflow-y: auto; 18 | } 19 | 20 | .split-pane.column .pane { 21 | width: 100%; 22 | } 23 | 24 | .split-pane.row .pane-trigger { 25 | width: 8px; 26 | height: 100%; 27 | cursor: e-resize; 28 | background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAPCAYAAADDNm69AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAeSURBVBhXY/4PBMzMzA379u1rANFMDGhgGAswMAAAn6EH6K9ktYAAAAAASUVORK5CYII=') 29 | 1px 50% no-repeat #f0f2f5; 30 | } 31 | 32 | .split-pane .collapse-btn { 33 | width: 25px; 34 | height: 70px; 35 | position: absolute; 36 | right: 8px; 37 | top: calc(50% - 35px); 38 | background-color: #f0f2f5; 39 | border-color: transparent; 40 | border-radius: 8px 0px 0px 8px; 41 | .anticon { 42 | color: #7cb0fe; 43 | } 44 | } 45 | 46 | .split-pane .spliter-wrap { 47 | position: relative; 48 | } 49 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/TagSelect/TagSelectOption.jsx: -------------------------------------------------------------------------------- 1 | import { Tag } from 'ant-design-vue' 2 | const { CheckableTag } = Tag 3 | 4 | export default { 5 | name: 'TagSelectOption', 6 | props: { 7 | prefixCls: { 8 | type: String, 9 | default: 'ant-pro-tag-select-option' 10 | }, 11 | value: { 12 | type: [String, Number, Object], 13 | default: '' 14 | }, 15 | checked: { 16 | type: Boolean, 17 | default: false 18 | } 19 | }, 20 | data () { 21 | return { 22 | localChecked: this.checked || false 23 | } 24 | }, 25 | watch: { 26 | 'checked' (val) { 27 | this.localChecked = val 28 | }, 29 | '$parent.items': { 30 | handler: function (val) { 31 | this.value && val.hasOwnProperty(this.value) && (this.localChecked = val[this.value]) 32 | }, 33 | deep: true 34 | } 35 | }, 36 | render () { 37 | const { $slots, value } = this 38 | const onChange = (checked) => { 39 | this.$emit('change', { value, checked }) 40 | } 41 | return ( 42 | {$slots.default} 43 | ) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/TwoColumnLayout/index.js: -------------------------------------------------------------------------------- 1 | import TwoColumnLayout from './TwoColumnLayout' 2 | export default TwoColumnLayout 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/_util/util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * components util 3 | */ 4 | 5 | /** 6 | * 清理空值,对象 7 | * @param children 8 | * @returns {*[]} 9 | */ 10 | export function filterEmpty (children = []) { 11 | return children.filter(c => c.tag || (c.text && c.text.trim() !== '')) 12 | } 13 | 14 | /** 15 | * 获取字符串长度,英文字符 长度1,中文字符长度2 16 | * @param {*} str 17 | */ 18 | export const getStrFullLength = (str = '') => 19 | str.split('').reduce((pre, cur) => { 20 | const charCode = cur.charCodeAt(0) 21 | if (charCode >= 0 && charCode <= 128) { 22 | return pre + 1 23 | } 24 | return pre + 2 25 | }, 0) 26 | 27 | /** 28 | * 截取字符串,根据 maxLength 截取后返回 29 | * @param {*} str 30 | * @param {*} maxLength 31 | */ 32 | export const cutStrByFullLength = (str = '', maxLength) => { 33 | let showLength = 0 34 | return str.split('').reduce((pre, cur) => { 35 | const charCode = cur.charCodeAt(0) 36 | if (charCode >= 0 && charCode <= 128) { 37 | showLength += 1 38 | } else { 39 | showLength += 2 40 | } 41 | if (showLength <= maxLength) { 42 | return pre + cur 43 | } 44 | return pre 45 | }, '') 46 | } 47 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/index.js: -------------------------------------------------------------------------------- 1 | import MultiTab from '@/components/MultiTab' 2 | import Result from '@/components/Result' 3 | import TagSelect from '@/components/TagSelect' 4 | import ExceptionPage from '@/components/Exception' 5 | 6 | export { 7 | MultiTab, 8 | Result, 9 | ExceptionPage, 10 | TagSelect 11 | } 12 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/index.less: -------------------------------------------------------------------------------- 1 | @import "~ant-design-vue/lib/style/index"; 2 | 3 | // The prefix to use on all css classes from ant-pro. 4 | @ant-pro-prefix : ant-pro; 5 | @ant-global-header-zindex : 105; -------------------------------------------------------------------------------- /cmdb-ui/src/components/tools/Breadcrumb.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/tools/DetailList.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/tools/DocumentLink.vue: -------------------------------------------------------------------------------- 1 | 9 | 22 | 39 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/tools/HeadInfo.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 32 | 33 | 68 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/tools/Logo.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 49 | -------------------------------------------------------------------------------- /cmdb-ui/src/components/tools/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/components/tools/index.js -------------------------------------------------------------------------------- /cmdb-ui/src/config/app.js: -------------------------------------------------------------------------------- 1 | const appConfig = { 2 | buildModules: ['cmdb', 'acl'], // 需要编译的模块 3 | redirectTo: '/cmdb', // 首页的重定向路径 4 | buildAclToModules: true, // 是否在各个应用下 内联权限管理 5 | showDocs: false, 6 | useEncryption: false, 7 | } 8 | 9 | export default appConfig 10 | -------------------------------------------------------------------------------- /cmdb-ui/src/config/setting.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 项目默认配置项 3 | * primaryColor - 默认主题色, 如果修改颜色不生效,请清理 localStorage 4 | * navTheme - sidebar theme ['dark', 'light'] 两种主题 5 | * colorWeak - 色盲模式 6 | * layout - 整体布局方式 ['sidemenu', 'topmenu'] 两种布局 7 | * fixedHeader - 固定 Header : boolean 8 | * fixSiderbar - 固定左侧菜单栏 : boolean 9 | * autoHideHeader - 向下滚动时,隐藏 Header : boolean 10 | * contentWidth - 内容区布局: 流式 | 固定 11 | * 12 | * storageOptions: {} - Vue-ls 插件配置项 (localStorage/sessionStorage) 13 | * 14 | */ 15 | 16 | export default { 17 | primaryColor: '#2f54eb', // primary color of ant design 18 | navTheme: 'dark', // theme for nav menu 19 | layout: 'sidemenu', // nav menu position: sidemenu or topmenu 20 | contentWidth: 'Fixed', // layout of content: Fluid or Fixed, only works when layout is topmenu 21 | fixedHeader: true, // sticky header 22 | fixSiderbar: true, // sticky siderbar 23 | autoHideHeader: true, // auto hide header 24 | colorWeak: false, 25 | multiTab: false, 26 | production: process.env.NODE_ENV === 'production' && process.env.VUE_APP_PREVIEW !== 'true', 27 | // vue-ls options 28 | storageOptions: { 29 | namespace: 'pro__', // key prefix 30 | name: 'ls', // name variable Vue.[ls] or this.[$ls], 31 | storage: 'local' // storage name session, local, memory 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /cmdb-ui/src/core/EventBus.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | export default new Vue() 4 | -------------------------------------------------------------------------------- /cmdb-ui/src/core/bootstrap.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import store from '@/store/' 3 | import { 4 | ACCESS_TOKEN, 5 | DEFAULT_COLOR, 6 | DEFAULT_THEME, 7 | DEFAULT_LAYOUT_MODE, 8 | DEFAULT_COLOR_WEAK, 9 | SIDEBAR_TYPE, 10 | DEFAULT_FIXED_HEADER, 11 | DEFAULT_FIXED_HEADER_HIDDEN, 12 | DEFAULT_FIXED_SIDEMENU, 13 | DEFAULT_CONTENT_WIDTH_TYPE, 14 | DEFAULT_MULTI_TAB 15 | } from '@/store/global/mutation-types' 16 | import config from '@/config/setting' 17 | 18 | export default function Initializer () { 19 | store.commit('SET_SIDEBAR_TYPE', Vue.ls.get(SIDEBAR_TYPE, true)) 20 | store.commit('TOGGLE_THEME', Vue.ls.get(DEFAULT_THEME, config.navTheme)) 21 | store.commit('TOGGLE_LAYOUT_MODE', Vue.ls.get(DEFAULT_LAYOUT_MODE, config.layout)) 22 | store.commit('TOGGLE_FIXED_HEADER', Vue.ls.get(DEFAULT_FIXED_HEADER, config.fixedHeader)) 23 | store.commit('TOGGLE_FIXED_SIDERBAR', Vue.ls.get(DEFAULT_FIXED_SIDEMENU, config.fixSiderbar)) 24 | store.commit('TOGGLE_CONTENT_WIDTH', Vue.ls.get(DEFAULT_CONTENT_WIDTH_TYPE, config.contentWidth)) 25 | store.commit('TOGGLE_FIXED_HEADER_HIDDEN', Vue.ls.get(DEFAULT_FIXED_HEADER_HIDDEN, config.autoHideHeader)) 26 | store.commit('TOGGLE_WEAK', Vue.ls.get(DEFAULT_COLOR_WEAK, config.colorWeak)) 27 | store.commit('TOGGLE_COLOR', Vue.ls.get(DEFAULT_COLOR, config.primaryColor)) 28 | store.commit('TOGGLE_MULTI_TAB', Vue.ls.get(DEFAULT_MULTI_TAB, config.multiTab)) 29 | store.commit('SET_TOKEN', Vue.ls.get(ACCESS_TOKEN)) 30 | // last step 31 | } 32 | -------------------------------------------------------------------------------- /cmdb-ui/src/core/directives/action.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import store from '@/store' 3 | 4 | /** 5 | * Action 权限指令 6 | * 指令用法: 7 | * - 在需要控制 action 级别权限的组件上使用 v-action:[method] , 如下: 8 | * 添加用户 9 | * 删除用户 10 | * 修改 11 | * 12 | * - 当前用户没有权限时,组件上使用了该指令则会被隐藏 13 | * - 当后台权限跟 pro 提供的模式不同时,只需要针对这里的权限过滤进行修改即可 14 | * 15 | * @see https://github.com/sendya/ant-design-pro-vue/pull/53 16 | */ 17 | const action = Vue.directive('action', { 18 | inserted: function (el, binding, vnode) { 19 | const actionName = binding.arg 20 | const roles = store.getters.roles 21 | const elVal = vnode.context.$route.meta.permission 22 | const permissionId = elVal instanceof String && [elVal] || elVal || [] 23 | roles.permissions.forEach(p => { 24 | if (!permissionId.includes(p.permissionId)) { 25 | return 26 | } 27 | if (p.actionList && !p.actionList.includes(actionName)) { 28 | el.parentNode && el.parentNode.removeChild(el) || (el.style.display = 'none') 29 | } 30 | }) 31 | } 32 | }) 33 | 34 | export default action 35 | -------------------------------------------------------------------------------- /cmdb-ui/src/core/icons.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom icon list 3 | * All icons are loaded here for easy management 4 | * @see https://vue.ant.design/components/icon/#Custom-Font-Icon 5 | * 6 | * 自定义图标加载表 7 | * 所有图标均从这里加载,方便管理 8 | */ 9 | import gridSvg from '@/assets/icons/grid.svg?inline' 10 | import top_agent from '@/assets/icons/top_agent.svg?inline' 11 | import top_acl from '@/assets/icons/top_acl.svg?inline' 12 | import ops_move_icon from '@/assets/icons/ops-move-icon.svg?inline' 13 | 14 | export { 15 | gridSvg, 16 | top_agent, 17 | top_acl, 18 | ops_move_icon 19 | } 20 | -------------------------------------------------------------------------------- /cmdb-ui/src/core/lazy_use.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueStorage from 'vue-ls' 3 | import config from '@/config/setting' 4 | 5 | // base library 6 | import '@/core/lazy_lib/components_use' 7 | import Viser from 'viser-vue' 8 | 9 | // ext library 10 | import VueClipboard from 'vue-clipboard2' 11 | import PermissionHelper from '@/utils/helper/permission' 12 | import './directives/action' 13 | 14 | VueClipboard.config.autoSetContainer = true 15 | 16 | Vue.use(Viser) 17 | 18 | Vue.use(VueStorage, config.storageOptions) 19 | Vue.use(VueClipboard) 20 | Vue.use(PermissionHelper) 21 | -------------------------------------------------------------------------------- /cmdb-ui/src/directive/highlight/highlight.js: -------------------------------------------------------------------------------- 1 | import './highlight.less' 2 | 3 | const highlight = (el, binding) => { 4 | if (binding.value.value) { 5 | let testValue = `${binding.value.value}` 6 | if (['(', ')', '$'].includes(testValue)) { 7 | testValue = `\\${testValue}` 8 | } 9 | const regex = new RegExp(`(${testValue})`, 'gi') 10 | el.innerHTML = el.innerText.replace(regex, `$1`) 11 | } 12 | } 13 | 14 | export default highlight 15 | -------------------------------------------------------------------------------- /cmdb-ui/src/directive/highlight/highlight.less: -------------------------------------------------------------------------------- 1 | @import '~@/style/static.less'; 2 | 3 | .ops-text-highlight { 4 | background-color: @primary-color_3; 5 | } 6 | -------------------------------------------------------------------------------- /cmdb-ui/src/directive/highlight/index.js: -------------------------------------------------------------------------------- 1 | import hightlight from './highlight' 2 | 3 | const install = function (Vue) { 4 | Vue.directive('hightlight', hightlight) 5 | } 6 | 7 | if (window.Vue) { 8 | window.hightlight = hightlight 9 | Vue.use(install); // eslint-disable-line 10 | } 11 | hightlight.install = install 12 | export default hightlight 13 | -------------------------------------------------------------------------------- /cmdb-ui/src/directive/waves/index.js: -------------------------------------------------------------------------------- 1 | import waves from './waves' 2 | 3 | const install = function (Vue) { 4 | Vue.directive('waves', waves) 5 | } 6 | 7 | if (window.Vue) { 8 | window.waves = waves 9 | Vue.use(install); // eslint-disable-line 10 | } 11 | 12 | waves.install = install 13 | export default waves 14 | -------------------------------------------------------------------------------- /cmdb-ui/src/directive/waves/waves.css: -------------------------------------------------------------------------------- 1 | .waves-ripple { 2 | position: absolute; 3 | border-radius: 100%; 4 | background-color: rgba(0, 0, 0, 0.15); 5 | background-clip: padding-box; 6 | pointer-events: none; 7 | -webkit-user-select: none; 8 | -moz-user-select: none; 9 | -ms-user-select: none; 10 | user-select: none; 11 | -webkit-transform: scale(0); 12 | -ms-transform: scale(0); 13 | transform: scale(0); 14 | opacity: 1; 15 | } 16 | 17 | .waves-ripple.z-active { 18 | opacity: 0; 19 | -webkit-transform: scale(2); 20 | -ms-transform: scale(2); 21 | transform: scale(2); 22 | -webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out; 23 | transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out; 24 | transition: opacity 1.2s ease-out, transform 0.6s ease-out; 25 | transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out; 26 | } -------------------------------------------------------------------------------- /cmdb-ui/src/lang/index.js: -------------------------------------------------------------------------------- 1 | import VueI18n from 'vue-i18n' 2 | import zh from './zh' 3 | import en from './en' 4 | import Vue from 'vue' 5 | import zhCN from 'vxe-table/lib/locale/lang/zh-CN' 6 | import enUS from 'vxe-table/lib/locale/lang/en-US' 7 | 8 | Vue.use(VueI18n) 9 | const i18n = new VueI18n({ 10 | locale: 'zh', // 初始化中文 11 | messages: { 12 | 'zh': { ...zh, ...zhCN }, 13 | 'en': { ...en, ...enUS }, 14 | }, 15 | silentTranslationWarn: true 16 | }) 17 | 18 | export default i18n 19 | -------------------------------------------------------------------------------- /cmdb-ui/src/layouts/BlankLayout.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | 17 | -------------------------------------------------------------------------------- /cmdb-ui/src/layouts/RouteView.vue: -------------------------------------------------------------------------------- 1 | 33 | -------------------------------------------------------------------------------- /cmdb-ui/src/layouts/index.js: -------------------------------------------------------------------------------- 1 | import UserLayout from './UserLayout' 2 | import BlankLayout from './BlankLayout' 3 | import BasicLayout from './BasicLayout' 4 | import RouteView from './RouteView' 5 | import PageView from './PageView' 6 | 7 | export { UserLayout, BasicLayout, BlankLayout, RouteView, PageView } 8 | -------------------------------------------------------------------------------- /cmdb-ui/src/main.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import '@babel/polyfill' 3 | import Vue from 'vue' 4 | import App from './App.vue' 5 | import router from './router' 6 | import store from './store/' 7 | import bootstrap from './core/bootstrap' 8 | import './core/use' 9 | import './guard' // guard permission control 10 | import './utils/filter' // global filter 11 | import Setting from './config/setting' 12 | import { Icon } from 'ant-design-vue' 13 | import i18n from './lang' 14 | 15 | import iconFont from '../public/iconfont/iconfont' 16 | 17 | // 存在直接crash的风险 还未到 18 | const customIcon = Icon.createFromIconfontCN(iconFont) 19 | Vue.component('ops-icon', customIcon) 20 | var vue; 21 | 22 | async function start() { 23 | const _vue = new Vue({ 24 | router, 25 | store, 26 | i18n, 27 | created: bootstrap, 28 | render: h => h(App) 29 | }).$mount('#app') 30 | vue = _vue 31 | 32 | if (process.env.NODE_ENV === 'development') { 33 | window.$app = vue 34 | window.$router = router 35 | window.$store = store 36 | window.$env = process.env 37 | } 38 | } 39 | 40 | start() 41 | window.$setting = Setting 42 | 43 | export default vue 44 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/acl/api/app.js: -------------------------------------------------------------------------------- 1 | import { axios } from '@/utils/request' 2 | 3 | const urlPrefix = '/v1/acl' 4 | 5 | export function searchRole(params) { 6 | return axios({ 7 | url: urlPrefix + `/roles`, 8 | method: 'GET', 9 | params: params 10 | }) 11 | } 12 | 13 | export function addRole(params) { 14 | return axios({ 15 | url: urlPrefix + '/roles', 16 | method: 'POST', 17 | data: params 18 | }) 19 | } 20 | 21 | export function updateRoleById(id, params) { 22 | return axios({ 23 | url: urlPrefix + `/roles/${id}`, 24 | method: 'PUT', 25 | data: params 26 | }) 27 | } 28 | 29 | export function deleteRoleById(id) { 30 | return axios({ 31 | url: urlPrefix + `/roles/${id}`, 32 | method: 'DELETE' 33 | }) 34 | } 35 | 36 | export function searchApp(params = {}) { 37 | return axios({ 38 | url: urlPrefix + '/apps', 39 | method: 'GET', 40 | params: { ...params, page_size: 9999 } 41 | }) 42 | } 43 | 44 | export function addApp(data) { 45 | return axios({ 46 | url: urlPrefix + '/apps', 47 | method: 'POST', 48 | data: data 49 | }) 50 | } 51 | 52 | export function updateApp(aid, data) { 53 | return axios({ 54 | url: urlPrefix + `/apps/${aid}`, 55 | method: 'PUT', 56 | data: data 57 | }) 58 | } 59 | 60 | export function getApp(aid) { 61 | return axios({ 62 | url: urlPrefix + `/apps/${aid}`, 63 | method: 'GET', 64 | }) 65 | } 66 | 67 | export function deleteApp(aid) { 68 | return axios({ 69 | url: urlPrefix + `/apps/${aid}`, 70 | method: 'DELETE' 71 | }) 72 | } 73 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/acl/api/history.js: -------------------------------------------------------------------------------- 1 | import { axios } from '@/utils/request' 2 | 3 | const urlPrefix = '/v1/acl' 4 | 5 | export function searchPermissonHistory(params) { 6 | return axios({ 7 | url: urlPrefix + `/audit_log/permission`, 8 | method: 'GET', 9 | params: params 10 | }) 11 | } 12 | 13 | export function searchRoleHistory(params) { 14 | return axios({ 15 | url: urlPrefix + `/audit_log/role`, 16 | method: 'GET', 17 | params: params 18 | }) 19 | } 20 | 21 | export function searchResourceHistory(params) { 22 | return axios({ 23 | url: urlPrefix + `/audit_log/resource`, 24 | method: 'GET', 25 | params: params 26 | }) 27 | } 28 | 29 | export function searchTriggerHistory(params) { 30 | return axios({ 31 | url: urlPrefix + `/audit_log/trigger`, 32 | method: 'GET', 33 | params: params 34 | }) 35 | } 36 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/acl/api/secretKey.js: -------------------------------------------------------------------------------- 1 | import { axios } from '@/utils/request' 2 | 3 | export function getSecret() { 4 | return axios({ 5 | url: '/v1/acl/users/secret', 6 | method: 'GET' 7 | }) 8 | } 9 | 10 | export function updateSecret(data) { 11 | return axios({ 12 | url: '/v1/acl/users/reset_key_secret', 13 | method: 'POST', 14 | data, 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/acl/api/trigger.js: -------------------------------------------------------------------------------- 1 | import { axios } from '@/utils/request' 2 | 3 | const urlPrefix = '/v1/acl' 4 | 5 | export function getTriggers(params) { 6 | return axios({ 7 | url: urlPrefix + '/triggers', 8 | method: 'GET', 9 | params: params 10 | }) 11 | } 12 | 13 | export function addTrigger(data) { 14 | return axios({ 15 | url: urlPrefix + '/triggers', 16 | method: 'POST', 17 | data: data 18 | }) 19 | } 20 | 21 | export function updateTrigger(tid, data) { 22 | return axios({ 23 | url: urlPrefix + `/triggers/${tid}`, 24 | method: 'PUT', 25 | data: data 26 | }) 27 | } 28 | 29 | export function deleteTrigger(tid) { 30 | return axios({ 31 | url: urlPrefix + `/triggers/${tid}`, 32 | method: 'DELETE' 33 | }) 34 | } 35 | 36 | export function applyTrigger(tid) { 37 | return axios({ 38 | url: urlPrefix + `/triggers/${tid}/apply`, 39 | method: 'POST' 40 | }) 41 | } 42 | 43 | export function cancelTrigger(tid) { 44 | return axios({ 45 | url: urlPrefix + `/triggers/${tid}/cancel`, 46 | method: 'POST' 47 | }) 48 | } 49 | 50 | export function patternResults(params) { 51 | return axios({ 52 | url: `${urlPrefix}/triggers/resources`, 53 | method: 'POST', 54 | data: params 55 | }) 56 | } 57 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/acl/api/user.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { axios } from '@/utils/request' 3 | 4 | const urlPrefix = '/v1/acl' 5 | 6 | export function currentUser() { 7 | return axios({ 8 | url: urlPrefix + `/users/info`, 9 | method: 'GET' 10 | }) 11 | } 12 | 13 | export function getOnDutyUser() { 14 | return axios({ 15 | url: urlPrefix + '/users/employee', 16 | method: 'GET', 17 | }) 18 | } 19 | 20 | export function searchUser(params) { 21 | return axios({ 22 | url: urlPrefix + `/users`, 23 | method: 'GET', 24 | params: params 25 | }) 26 | } 27 | 28 | export function addUser(params) { 29 | return axios({ 30 | url: urlPrefix + '/users', 31 | method: 'POST', 32 | data: params 33 | }) 34 | } 35 | 36 | export function updateUserById(id, params) { 37 | return axios({ 38 | url: urlPrefix + `/users/${id}`, 39 | method: 'PUT', 40 | data: params 41 | }) 42 | } 43 | 44 | export function deleteUserById(id) { 45 | return axios({ 46 | url: urlPrefix + `/users/${id}`, 47 | method: 'DELETE' 48 | }) 49 | } 50 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/acl/constants/constants.js: -------------------------------------------------------------------------------- 1 | export const valueTypeMap = { 2 | '0': '整数', 3 | '1': '浮点数', 4 | '2': '文本', 5 | '3': 'datetime', 6 | '4': 'date', 7 | '5': 'time', 8 | '6': 'json' 9 | } 10 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/acl/index.js: -------------------------------------------------------------------------------- 1 | import genAclRoutes from './router' 2 | 3 | export default { 4 | name: 'acl', 5 | route: genAclRoutes 6 | } 7 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/acl/store/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/acl/store/index.js -------------------------------------------------------------------------------- /cmdb-ui/src/modules/acl/style/index.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/acl/style/index.css -------------------------------------------------------------------------------- /cmdb-ui/src/modules/acl/style/index.less: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/acl/style/index.less -------------------------------------------------------------------------------- /cmdb-ui/src/modules/acl/views/module/resourceGroupMember.vue: -------------------------------------------------------------------------------- 1 | 10 | 36 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/acl/views/operation_history/index.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 33 | 34 | 44 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/3rd/relation-graph/GraphBottomPanel.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 37 | 38 | 56 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/3rd/relation-graph/GraphMiniNameFilter.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 42 | 54 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/3rd/relation-graph/core4vue/layouters/SeeksFixedLayouter.js: -------------------------------------------------------------------------------- 1 | import SeeksGraphMath from '../SeeksGraphMath' 2 | 3 | function SeeksFixedLayouter(layoutSetting, graphSetting) { 4 | this.graphSetting = graphSetting 5 | this.config = layoutSetting || {} 6 | this.rootNode = null 7 | this.allNodes = [] 8 | this.__origin_nodes = [] 9 | this.refresh = function() { 10 | this.placeNodes(this.__origin_nodes, this.rootNode) 11 | } 12 | this.placeNodes = function(allNodes, rootNode) { 13 | if (!rootNode) { 14 | console.log('root is null:', rootNode) 15 | return 16 | } else { 17 | if (window.SeeksGraphDebug) console.log('layout by root:', rootNode) 18 | } 19 | this.__origin_nodes = allNodes 20 | this.rootNode = rootNode 21 | allNodes.forEach(thisNode => { 22 | // thisNode.lot = { eached: false } 23 | thisNode.lot.eached = false 24 | thisNode.lot.notLeafNode = false 25 | thisNode.lot.childs = [] 26 | // thisNode.lot.parent = undefined 27 | thisNode.lot.index_of_parent = 0 28 | thisNode.lot.strength = 0 29 | thisNode.lot.prevNode = undefined 30 | thisNode.lot.nextNode = undefined 31 | thisNode.lot.placed = false 32 | }) 33 | this.allNodes = [] 34 | var analyticResult = { 35 | max_deep: 1, 36 | max_length: 1 37 | } 38 | SeeksGraphMath.analysisNodes4Didirectional(this.allNodes, [this.rootNode], 0, analyticResult, 0) 39 | if (window.SeeksGraphDebug) console.log('[layout canvasOffset]', this.graphSetting.viewSize, this.graphSetting.canvasSize) 40 | } 41 | } 42 | 43 | export default SeeksFixedLayouter 44 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/3rd/relation-graph/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import RelationGraph from './index.vue' 3 | RelationGraph.install = function(Vue) { 4 | Vue.component('relation-graph', RelationGraph); 5 | Vue.component('seeks-relation-graph', RelationGraph); 6 | }; 7 | export default RelationGraph 8 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/api/ci.js: -------------------------------------------------------------------------------- 1 | import { axios } from '@/utils/request' 2 | 3 | const urlPrefix = '/v0.1' 4 | 5 | export function searchCI(params, isShowMessage = true) { 6 | return axios({ 7 | url: urlPrefix + `/ci/s`, 8 | method: 'GET', 9 | params: params, 10 | isShowMessage 11 | }) 12 | } 13 | 14 | export function searchCI2(params) { 15 | return axios({ 16 | url: urlPrefix + `/ci/s?${params}`, 17 | method: 'GET' 18 | }) 19 | } 20 | 21 | export function addCI(params) { 22 | return axios({ 23 | url: urlPrefix + '/ci', 24 | method: 'POST', 25 | data: params 26 | }) 27 | } 28 | 29 | export function updateCI(id, params, isShowMessage = true) { 30 | return axios({ 31 | url: urlPrefix + `/ci/${id}`, 32 | method: 'PUT', 33 | data: params, 34 | isShowMessage 35 | }) 36 | } 37 | 38 | export function deleteCI(ciId, isShowMessage = true) { 39 | return axios({ 40 | url: urlPrefix + `/ci/${ciId}`, 41 | method: 'DELETE', 42 | isShowMessage 43 | }) 44 | } 45 | 46 | // 获取单个ci实例 47 | export function getCIById(ciId) { 48 | return axios({ 49 | // url: urlPrefix + `/ci/${ciId}`, 50 | url: urlPrefix + `/ci/s?q=_id:${ciId}`, 51 | method: 'GET' 52 | }) 53 | } 54 | 55 | // 获取自动发现占比 56 | export function getCIAdcStatistics() { 57 | return axios({ 58 | url: urlPrefix + `/ci/adc/statistics`, 59 | method: 'GET' 60 | }) 61 | } 62 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/api/ciTypeGroup.js: -------------------------------------------------------------------------------- 1 | import { axios } from '@/utils/request' 2 | 3 | const urlPrefix = '/v0.1' 4 | 5 | export function getCITypeGroups(params) { 6 | return axios({ 7 | url: `${urlPrefix}/ci_types/groups`, 8 | method: 'GET', 9 | params: params 10 | }) 11 | } 12 | 13 | export function postCITypeGroup(data) { 14 | return axios({ 15 | url: `${urlPrefix}/ci_types/groups`, 16 | method: 'POST', 17 | data: data 18 | }) 19 | } 20 | 21 | export function putCITypeGroupByGId(gid, data) { 22 | return axios({ 23 | url: `${urlPrefix}/ci_types/groups/${gid}`, 24 | method: 'PUT', 25 | data: data 26 | }) 27 | } 28 | 29 | export function deleteCITypeGroup(gid, data) { 30 | return axios({ 31 | url: `${urlPrefix}/ci_types/groups/${gid}`, 32 | method: 'DELETE', 33 | data: data 34 | }) 35 | } 36 | 37 | export function getCITypeGroupsConfig(params) { 38 | return axios({ 39 | url: `${urlPrefix}/ci_types/groups/config`, 40 | method: 'GET', 41 | params: params 42 | }) 43 | } 44 | 45 | // 更新模型配置分组的排序 46 | export const putCITypeGroups = (data) => { 47 | return axios({ 48 | url: `${urlPrefix}/ci_types/groups/order`, 49 | method: 'PUT', 50 | data: data 51 | }) 52 | } 53 | 54 | // 导出模型分组 55 | export function exportCITypeGroups(params) { 56 | return axios({ 57 | url: `${urlPrefix}/ci_types/template/export`, 58 | method: 'GET', 59 | params: params, 60 | timeout: 30 * 1000, 61 | }) 62 | } 63 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/api/customDashboard.js: -------------------------------------------------------------------------------- 1 | import { axios } from '@/utils/request' 2 | 3 | export function getCustomDashboard() { 4 | return axios({ 5 | url: '/v0.1/custom_dashboard', 6 | method: 'get', 7 | }) 8 | } 9 | 10 | export function postCustomDashboard(data) { 11 | return axios({ 12 | url: '/v0.1/custom_dashboard', 13 | method: 'post', 14 | data 15 | }) 16 | } 17 | 18 | export function putCustomDashboard(id, data) { 19 | return axios({ 20 | url: `/v0.1/custom_dashboard/${id}`, 21 | method: 'put', 22 | data 23 | }) 24 | } 25 | 26 | export function deleteCustomDashboard(id) { 27 | return axios({ 28 | url: `/v0.1/custom_dashboard/${id}`, 29 | method: 'delete', 30 | }) 31 | } 32 | 33 | export function batchUpdateCustomDashboard(data) { 34 | return axios({ 35 | url: `/v0.1/custom_dashboard/batch`, 36 | method: 'put', 37 | data 38 | }) 39 | } 40 | 41 | export function postCustomDashboardPreview(data) { 42 | return axios({ 43 | url: '/v0.1/custom_dashboard/preview', 44 | method: 'post', 45 | data 46 | }) 47 | } 48 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/api/perm.js: -------------------------------------------------------------------------------- 1 | import { axios } from '@/utils/request' 2 | 3 | export function getWX() { 4 | return axios({ 5 | url: '/v1/acl/users', 6 | method: 'GET' 7 | }) 8 | } 9 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/api/relationType.js: -------------------------------------------------------------------------------- 1 | import { axios } from '@/utils/request' 2 | 3 | export function getRelationTypes () { 4 | return axios({ 5 | url: '/v0.1/relation_types', 6 | method: 'GET' 7 | }) 8 | } 9 | 10 | export function addRelationType (payload) { 11 | return axios({ 12 | url: `/v0.1/relation_types`, 13 | method: 'POST', 14 | data: payload 15 | }) 16 | } 17 | 18 | export function updateRelationType (rtId, payload) { 19 | return axios({ 20 | url: `/v0.1/relation_types/${rtId}`, 21 | method: 'PUT', 22 | data: payload 23 | }) 24 | } 25 | 26 | export function deleteRelationType (rtId) { 27 | return axios({ 28 | url: `/v0.1/relation_types/${rtId}`, 29 | method: 'DELETE' 30 | }) 31 | } 32 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/api/statistics.js: -------------------------------------------------------------------------------- 1 | import { axios } from '@/utils/request' 2 | 3 | export function getStatistics() { 4 | return axios({ 5 | url: '/v0.1/statistics', 6 | method: 'GET' 7 | }) 8 | } 9 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/api/system_config.js: -------------------------------------------------------------------------------- 1 | import { axios } from '@/utils/request' 2 | 3 | // 保存布局 4 | export function saveSystemConfig(data) { 5 | return axios({ 6 | url: '/v0.1/system_config', 7 | method: 'POST', 8 | data 9 | }) 10 | } 11 | 12 | // 获取布局 13 | export function getSystemConfig(params) { 14 | return axios({ 15 | url: '/v0.1/system_config', 16 | method: 'GET', 17 | params 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/dashboard_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/dashboard_empty.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/dcim/dcim_null.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/dcim/dcim_null.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/dcim/device/firewall_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/dcim/device/firewall_front.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/dcim/device/firewall_rear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/dcim/device/firewall_rear.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/dcim/device/raid_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/dcim/device/raid_front.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/dcim/device/raid_rear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/dcim/device/raid_rear.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/dcim/device/router_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/dcim/device/router_front.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/dcim/device/router_rear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/dcim/device/router_rear.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/dcim/device/server_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/dcim/device/server_front.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/dcim/device/server_rear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/dcim/device/server_rear.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/dcim/device/switch_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/dcim/device/switch_front.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/dcim/device/switch_rear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/dcim/device/switch_rear.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/dcim/device_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/dcim/device_2.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/dcim/rack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/dcim/rack.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/dcim/rack_front_part.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/dcim/rack_front_part.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/dcim/rack_rear_part.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/dcim/rack_rear_part.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/ipam_address_null.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/ipam_address_null.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/itsm_uninstalled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/itsm_uninstalled.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/no_permission.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/no_permission.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/preference_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/preference_background.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/preference_card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/preference_card.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/resourceSearch/resource_search_bg_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/resourceSearch/resource_search_bg_1.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/resourceSearch/resource_search_bg_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/resourceSearch/resource_search_bg_2.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/assets/unique_card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/modules/cmdb/assets/unique_card.png -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/components/cmdbGrant/constants.js: -------------------------------------------------------------------------------- 1 | import i18n from '@/lang' 2 | 3 | export const permMap = () => { 4 | return { 5 | read: i18n.t('view'), 6 | add: i18n.t('new'), 7 | create: i18n.t('new'), 8 | update: i18n.t('update'), 9 | delete: i18n.t('delete'), 10 | config: i18n.t('cmdb.components.config'), 11 | grant: i18n.t('grant'), 12 | 'read_attr': i18n.t('cmdb.components.readAttribute'), 13 | 'read_ci': i18n.t('cmdb.components.readCI') 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/components/cmdbGrant/index.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/components/cmdbGrant/utils.js: -------------------------------------------------------------------------------- 1 | export const getCurrentRowStyle = ({ row }, addedRids) => { 2 | const idx = addedRids.findIndex(item => item.rid === row.rid) 3 | return idx > -1 ? 'background-color:#E0E7FF!important' : '' 4 | } 5 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/components/cmdbTypeSelect/index.js: -------------------------------------------------------------------------------- 1 | import CMDBTypeSelect from './cmdbTypeSelect.vue' 2 | export default CMDBTypeSelect 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/components/conditionFilter/constants.js: -------------------------------------------------------------------------------- 1 | import i18n from '@/lang' 2 | 3 | export const ruleTypeList = () => { 4 | return [ 5 | { value: 'and', label: i18n.t('cmdbFilterComp.and') }, 6 | { value: 'or', label: i18n.t('cmdbFilterComp.or') }, 7 | // { value: 'not', label: '非' }, 8 | ] 9 | } 10 | 11 | export const expList = () => { 12 | return [ 13 | { value: 'is', label: i18n.t('cmdbFilterComp.is') }, 14 | { value: '~is', label: i18n.t('cmdbFilterComp.~is') }, 15 | { value: 'contain', label: i18n.t('cmdbFilterComp.contain') }, 16 | { value: '~contain', label: i18n.t('cmdbFilterComp.~contain') }, 17 | { value: 'start_with', label: i18n.t('cmdbFilterComp.start_with') }, 18 | { value: '~start_with', label: i18n.t('cmdbFilterComp.~start_with') }, 19 | { value: 'end_with', label: i18n.t('cmdbFilterComp.end_with') }, 20 | { value: '~end_with', label: i18n.t('cmdbFilterComp.~end_with') }, 21 | { value: '~value', label: i18n.t('cmdbFilterComp.~value') }, // 为空的定义有点绕 22 | { value: 'value', label: i18n.t('cmdbFilterComp.value') }, 23 | ] 24 | } 25 | 26 | export const advancedExpList = () => { 27 | return [ 28 | { value: 'in', label: i18n.t('cmdbFilterComp.in') }, 29 | { value: '~in', label: i18n.t('cmdbFilterComp.~in') }, 30 | { value: 'range', label: i18n.t('cmdbFilterComp.range') }, 31 | { value: '~range', label: i18n.t('cmdbFilterComp.~range') }, 32 | { value: 'compare', label: i18n.t('cmdbFilterComp.compare') }, 33 | ] 34 | } 35 | 36 | export const compareTypeList = [ 37 | { value: '1', label: '>' }, 38 | { value: '2', label: '>=' }, 39 | { value: '3', label: '<' }, 40 | { value: '4', label: '<=' }, 41 | ] 42 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/components/httpSnmpAD/adPreviewTable.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 37 | 38 | 40 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/components/noticeContent/index.js: -------------------------------------------------------------------------------- 1 | import NoticeContent from './index.vue' 2 | export default NoticeContent 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/components/passwordField/index.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/components/webhook/index.js: -------------------------------------------------------------------------------- 1 | import Webhook from './index.vue' 2 | export default Webhook 3 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | 返回一个module对象 3 | 4 | routes: [] 5 | stores: [] 6 | 到时间都会插入到二级下面 7 | 8 | 会被插入到全局中 9 | 是否设置一个钩子呢? 10 | 插入前 调用的钩子? 11 | 12 | */ 13 | import genCmdbRoutes from './router' 14 | import cmdbStore from './store' 15 | 16 | export default { 17 | name: 'cmdb', 18 | route: genCmdbRoutes, 19 | store: cmdbStore 20 | } 21 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/store/index.js: -------------------------------------------------------------------------------- 1 | const cmdbStore = { 2 | namespaced: true, 3 | name: 'cmdbStore', 4 | state: { 5 | isTableLoading: false, 6 | }, 7 | actions: { 8 | }, 9 | mutations: { 10 | SET_IS_TABLE_LOADING(state, payload) { 11 | state.isTableLoading = payload 12 | }, 13 | }, 14 | } 15 | 16 | export default cmdbStore 17 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/utils/const.js: -------------------------------------------------------------------------------- 1 | import i18n from '@/lang' 2 | 3 | export const valueTypeMap = () => { 4 | return { 5 | '0': i18n.t('cmdb.ciType.int'), 6 | '1': i18n.t('cmdb.ciType.float'), 7 | '2': i18n.t('cmdb.ciType.shortText'), 8 | '3': i18n.t('cmdb.ciType.datetime'), 9 | '4': i18n.t('cmdb.ciType.date'), 10 | '5': i18n.t('cmdb.ciType.time'), 11 | '6': 'JSON', 12 | '7': i18n.t('cmdb.ciType.password'), 13 | '8': i18n.t('cmdb.ciType.link'), 14 | '9': i18n.t('cmdb.ciType.longText'), 15 | '10': i18n.t('cmdb.ciType.bool'), 16 | '11': i18n.t('cmdb.ciType.reference'), 17 | } 18 | } 19 | 20 | export const defautValueColor = [ 21 | { value: '#d9d9d9' }, 22 | { value: '#ffccc7' }, 23 | { value: '#ffd8bf' }, 24 | { value: '#ffe7ba' }, 25 | { value: '#fff1b8' }, 26 | { value: '#f4ffb8' }, 27 | { value: '#d9f7be' }, 28 | { value: '#b5f5ec' }, 29 | { value: '#bae7ff' }, 30 | { value: '#d6e4ff' }, 31 | { value: '#efdbff' }, 32 | { value: '#ffd6e7' }, 33 | ] 34 | 35 | export const defaultBGColors = ['#ffccc7', '#ffd8bf', '#ffe7ba', '#fff1b8', '#d9f7be', '#b5f5ec', '#bae7ff', '#d6e4ff', '#efdbff', '#ffd6e7'] 36 | 37 | export const CI_DEFAULT_ATTR = { 38 | UPDATE_USER: '_updated_by', 39 | UPDATE_TIME: '_updated_at' 40 | } 41 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/ci/modules/ciDetailComponent/ciDetailTableTitle.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | 19 | 58 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/ci/modules/ciDetailComponent/ciDetailTitle.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 49 | 50 | 65 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/ci/modules/ciDetailDrawer.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 52 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/ci_types/attrAD/SNMPScanningConfig/index.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 69 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/ci_types/attrAD/constants.js: -------------------------------------------------------------------------------- 1 | export const TAB_KEY = { 2 | CUSTOM: 'custom', 3 | CONFIG: 'config' 4 | } 5 | 6 | export const tabList = [ 7 | { 8 | key: TAB_KEY.CUSTOM, 9 | text: 'cmdb.ad.tabCustom' 10 | }, 11 | { 12 | key: TAB_KEY.CONFIG, 13 | text: 'cmdb.ad.tabConfig' 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/ci_types/attrAD/portScanConfig/index.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 50 | 51 | 53 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/ci_types/iconArea.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 38 | 39 | 54 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/ci_types/preValueAttr/builtin/userFilterComp/constants.js: -------------------------------------------------------------------------------- 1 | export const ruleTypeList = [ 2 | { value: '&', label: 'cs.components.and' }, 3 | { value: '|', label: 'cs.components.or' }, 4 | ] 5 | 6 | export const expList = [ 7 | { value: 1, label: 'cs.components.equal' }, 8 | { value: 2, label: 'cs.components.notEqual' }, 9 | { value: 7, label: 'cs.components.isEmpty' }, 10 | { value: 8, label: 'cs.components.isNotEmpty' }, 11 | ] 12 | 13 | export const compareTypeList = [ 14 | { value: 5, label: 'cs.components.moreThan' }, 15 | { value: 6, label: 'cs.components.lessThan' }, 16 | ] 17 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/custom_dashboard/colorListPicker.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 45 | 46 | 53 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/custom_dashboard/constant.js: -------------------------------------------------------------------------------- 1 | import i18n from '@/lang' 2 | 3 | export const dashboardCategory = () => { 4 | return { 5 | 1: { label: i18n.t('cmdb.custom_dashboard.default') }, 6 | 2: { label: i18n.t('cmdb.custom_dashboard.relation') } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/custom_dashboard/fontConfig.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/custom_dashboard/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/dashboard/components/dashboardCard.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 27 | 28 | 37 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/dashboard/constants.js: -------------------------------------------------------------------------------- 1 | export const dashboardList = [{ 2 | title: '资源总览', span: '16', component: 'SummaryCounter' 3 | }, { 4 | title: '系统总览', span: '8', component: 'SystemCounter' 5 | }, { 6 | title: '业务总览', span: '24', component: 'BusinessCounter' 7 | }] 8 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/dashboard/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/dashboard/index_v2.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/dcim/components/dcimMain/rackTable.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 50 | 51 | 53 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/dcim/components/rackDetail/rackView/rackHeader/rackHeaderCircle.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 16 | 17 | 67 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/dcim/constants.js: -------------------------------------------------------------------------------- 1 | export const DCIM_TYPE = { 2 | REGION: 'region', 3 | IDC: 'idc', 4 | SERVER_ROOM: 'server_room', 5 | RACK: 'rack' 6 | } 7 | 8 | export const DCIM_CITYPE_NAME = { 9 | REGION: 'dcim_region', 10 | IDC: 'dcim_idc', 11 | SERVER_ROOM: 'dcim_server_room', 12 | RACK: 'dcim_rack' 13 | } 14 | 15 | export const DEVICE_CITYPE_NAME = { 16 | SWITCH: 'switch', 17 | FC_SWITCH: 'fc_switch', 18 | F5: 'bigip', 19 | ROUTER: 'router', 20 | FIRE_WALL: 'firewall', 21 | SERVER: 'server', 22 | RAID: 'raid' 23 | } 24 | 25 | const createTypeNameMap = (typeObj, typeNameObj) => { 26 | const map = {} 27 | 28 | Object.keys(typeObj).forEach(key => { 29 | map[typeObj[key]] = typeNameObj[key] 30 | map[typeNameObj[key]] = typeObj[key] 31 | }) 32 | 33 | return map 34 | } 35 | 36 | export const DCIM_TYPE_NAME_MAP = createTypeNameMap(DCIM_TYPE, DCIM_CITYPE_NAME) 37 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/discovery/accountConfig/constants.js: -------------------------------------------------------------------------------- 1 | export const defaultConfig = { 2 | public: { 3 | key: '', 4 | secret: '' 5 | }, 6 | vcenter: { 7 | host: '', 8 | account: '', 9 | password: '' 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/discovery/agentTable.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 34 | 35 | 37 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/discovery/constants.js: -------------------------------------------------------------------------------- 1 | export const DISCOVERY_CATEGORY_TYPE = { 2 | AGENT: 'agent', 3 | SNMP: 'snmp', 4 | HTTP: 'http', 5 | PLUGIN: 'plugin', 6 | COMPONENT: 'components', 7 | PRIVATE_CLOUD: 'private_cloud' 8 | } 9 | 10 | export const PRIVATE_CLOUD_NAME = { 11 | VCenter: 'vcenter' 12 | } 13 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/discoveryCI/components/passwordField.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 36 | 37 | 42 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/fullscreen/processLine.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 40 | 41 | 44 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/ipam/constants.js: -------------------------------------------------------------------------------- 1 | export const SUB_NET_CITYPE_NAME = 'ipam_subnet' 2 | export const SCOPE_CITYPE_NAME = 'ipam_scope' 3 | export const ADDRESS_CITYPE_NAME = 'ipam_address' 4 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/ipam/modules/address/constants.js: -------------------------------------------------------------------------------- 1 | export const ADDRESS_STATUS = { 2 | ONLINE_ASSIGNED: '0', 3 | ONLINE_UNASSIGNED: '1', 4 | OFFLINE_ASSIGNED: '2', 5 | OFFLINE_UNASSIGNED: '3', 6 | } 7 | 8 | export const STATUS_COLOR = { 9 | [ADDRESS_STATUS.ONLINE_ASSIGNED]: '#00B42A', 10 | [ADDRESS_STATUS.ONLINE_UNASSIGNED]: '#FF7D00', 11 | [ADDRESS_STATUS.OFFLINE_ASSIGNED]: '#2F54EB', 12 | [ADDRESS_STATUS.OFFLINE_UNASSIGNED]: '#A5A9BC' 13 | } 14 | 15 | export const STATUS_LABEL = { 16 | [ADDRESS_STATUS.ONLINE_ASSIGNED]: 'cmdb.ipam.assignedOnline', 17 | [ADDRESS_STATUS.ONLINE_UNASSIGNED]: 'cmdb.ipam.unassignedOnline', 18 | [ADDRESS_STATUS.OFFLINE_ASSIGNED]: 'cmdb.ipam.assignedOffline', 19 | [ADDRESS_STATUS.OFFLINE_UNASSIGNED]: 'cmdb.ipam.unused' 20 | } 21 | 22 | export const STATUS_OPTION = [ 23 | { 24 | value: ADDRESS_STATUS.ONLINE_ASSIGNED, 25 | label: STATUS_LABEL[ADDRESS_STATUS.ONLINE_ASSIGNED], 26 | }, 27 | { 28 | value: ADDRESS_STATUS.ONLINE_UNASSIGNED, 29 | label: STATUS_LABEL[ADDRESS_STATUS.ONLINE_UNASSIGNED], 30 | }, 31 | { 32 | value: ADDRESS_STATUS.OFFLINE_ASSIGNED, 33 | label: STATUS_LABEL[ADDRESS_STATUS.OFFLINE_ASSIGNED], 34 | }, 35 | { 36 | value: ADDRESS_STATUS.OFFLINE_UNASSIGNED, 37 | label: STATUS_LABEL[ADDRESS_STATUS.OFFLINE_UNASSIGNED], 38 | } 39 | ] 40 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/ipam/modules/history/operation/constants.js: -------------------------------------------------------------------------------- 1 | export const OPERATE_TYPE = { 2 | ADD_SCOPE: '0', 3 | UPDATE_SCOPE: '1', 4 | DELETE_SCOPE: '2', 5 | ADD_SUBNET: '3', 6 | UPDATE_SUBNET: '4', 7 | DELETE_SUBNET: '5', 8 | ASSIGN_ADDRESS: '6', 9 | REVOKE_ADDRESS: '7', 10 | } 11 | 12 | export const OPERATE_TYPE_TEXT = { 13 | [OPERATE_TYPE.ADD_SCOPE]: 'cmdb.ipam.addCatalog', 14 | [OPERATE_TYPE.UPDATE_SCOPE]: 'cmdb.ipam.updateCatalog', 15 | [OPERATE_TYPE.DELETE_SCOPE]: 'cmdb.ipam.deleteCatalog', 16 | [OPERATE_TYPE.ADD_SUBNET]: 'cmdb.ipam.addSubnet', 17 | [OPERATE_TYPE.UPDATE_SUBNET]: 'cmdb.ipam.updateSubnet', 18 | [OPERATE_TYPE.DELETE_SUBNET]: 'cmdb.ipam.deleteSubnet', 19 | [OPERATE_TYPE.ASSIGN_ADDRESS]: 'cmdb.ipam.addressAssign', 20 | [OPERATE_TYPE.REVOKE_ADDRESS]: 'cmdb.ipam.revokeAddress', 21 | } 22 | 23 | export const OPERATE_TYPE_COLOR = { 24 | [OPERATE_TYPE.ADD_SCOPE]: { 25 | color: '#2F54EB', 26 | backgroundColor: '#DCF5FF' 27 | }, 28 | [OPERATE_TYPE.UPDATE_SCOPE]: { 29 | color: '#FF7D00', 30 | backgroundColor: '#FFECCF' 31 | }, 32 | [OPERATE_TYPE.DELETE_SCOPE]: { 33 | color: '#FD4C6A', 34 | backgroundColor: '#FFECE8' 35 | }, 36 | [OPERATE_TYPE.ADD_SUBNET]: { 37 | color: '#2F54EB', 38 | backgroundColor: '#DCF5FF' 39 | }, 40 | [OPERATE_TYPE.UPDATE_SUBNET]: { 41 | color: '#FF7D00', 42 | backgroundColor: '#FFECCF' 43 | }, 44 | [OPERATE_TYPE.DELETE_SUBNET]: { 45 | color: '#FD4C6A', 46 | backgroundColor: '#FFECE8' 47 | }, 48 | [OPERATE_TYPE.ASSIGN_ADDRESS]: { 49 | color: '#00B42A', 50 | backgroundColor: '#F6FFED' 51 | }, 52 | [OPERATE_TYPE.REVOKE_ADDRESS]: { 53 | color: '#0AA5A8', 54 | backgroundColor: '#E8FFFB' 55 | }, 56 | } 57 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/ipam/modules/overview/index.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 60 | 61 | 66 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/operation_history/index.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 42 | 43 | 50 | -------------------------------------------------------------------------------- /cmdb-ui/src/modules/cmdb/views/resource_search_2/resourceSearch/constants.js: -------------------------------------------------------------------------------- 1 | export const SEARCH_MODE = { 2 | NORMAL: 'normal', 3 | COLUMN: 'column' 4 | } 5 | -------------------------------------------------------------------------------- /cmdb-ui/src/router/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import Vue from 'vue' 3 | import Router from 'vue-router' 4 | import { constantRouterMap } from '@/router/config' 5 | 6 | Vue.use(Router) 7 | 8 | const createRouter = () => new Router({ 9 | mode: 'history', 10 | base: process.env.BASE_URL, 11 | scrollBehavior: () => ({ y: 0, x: undefined }), 12 | routes: constantRouterMap 13 | }) 14 | 15 | const router = createRouter() 16 | 17 | export function resetRouter () { 18 | const newRouter = createRouter() 19 | router['matcher'] = newRouter['matcher'] // reset router 20 | } 21 | 22 | export default router 23 | -------------------------------------------------------------------------------- /cmdb-ui/src/store/global/company.js: -------------------------------------------------------------------------------- 1 | const company = { 2 | state: { 3 | name: undefined 4 | }, 5 | mutations: { 6 | SET_COMPANY_NAME: (state, name) => { 7 | state.name = name 8 | }, 9 | }, 10 | } 11 | export default company 12 | -------------------------------------------------------------------------------- /cmdb-ui/src/store/global/getters.js: -------------------------------------------------------------------------------- 1 | const getters = { 2 | device: state => state.app.device, 3 | theme: state => state.app.theme, 4 | color: state => state.app.color, 5 | token: state => state.user.token, 6 | avatar: state => state.user.avatar, 7 | nickname: state => state.user.name, 8 | username: state => state.user.username, 9 | uid: state => state.user.uid, 10 | rid: state => state.user.rid, 11 | welcome: state => state.user.welcome, 12 | roles: state => state.user.roles, 13 | userInfo: state => state.user.info, 14 | appRoutes: state => state.routes.appRoutes, 15 | multiTab: state => state.app.multiTab, 16 | } 17 | 18 | export default getters 19 | -------------------------------------------------------------------------------- /cmdb-ui/src/store/global/mutation-types.js: -------------------------------------------------------------------------------- 1 | export const ACCESS_TOKEN = 'Access-Token' 2 | export const SIDEBAR_TYPE = 'SIDEBAR_TYPE' 3 | export const DEFAULT_THEME = 'DEFAULT_THEME' 4 | export const DEFAULT_LAYOUT_MODE = 'DEFAULT_LAYOUT_MODE' 5 | export const DEFAULT_COLOR = 'DEFAULT_COLOR' 6 | export const DEFAULT_COLOR_WEAK = 'DEFAULT_COLOR_WEAK' 7 | export const DEFAULT_FIXED_HEADER = 'DEFAULT_FIXED_HEADER' 8 | export const DEFAULT_FIXED_SIDEMENU = 'DEFAULT_FIXED_SIDEMENU' 9 | export const DEFAULT_FIXED_HEADER_HIDDEN = 'DEFAULT_FIXED_HEADER_HIDDEN' 10 | export const DEFAULT_CONTENT_WIDTH_TYPE = 'DEFAULT_CONTENT_WIDTH_TYPE' 11 | export const DEFAULT_MULTI_TAB = 'DEFAULT_MULTI_TAB' 12 | 13 | export const CONTENT_WIDTH_TYPE = { 14 | Fluid: 'Fluid', 15 | Fixed: 'Fixed' 16 | } 17 | -------------------------------------------------------------------------------- /cmdb-ui/src/store/global/notice.js: -------------------------------------------------------------------------------- 1 | const notice = { 2 | state: { 3 | totalUnreadNum: 0, 4 | appUnreadNum: [] 5 | }, 6 | mutations: { 7 | SET_TOTAL_UNREAD_NUM: (state, totalUnreadNum) => { 8 | state.totalUnreadNum = totalUnreadNum 9 | }, 10 | SET_APP_UNREAD_NUM: (state, appUnreadNum) => { 11 | state.appUnreadNum = appUnreadNum 12 | }, 13 | }, 14 | actions: { 15 | } 16 | } 17 | export default notice 18 | -------------------------------------------------------------------------------- /cmdb-ui/src/store/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | import Vue from 'vue' 4 | import Vuex from 'vuex' 5 | import app from './global/app' 6 | import user from './global/user' 7 | import routes from './global/routes' 8 | import notice from './global/notice' 9 | import getters from './global/getters' 10 | import company from './global/company' 11 | import appConfig from '@/config/app' 12 | 13 | Vue.use(Vuex) 14 | 15 | const store = new Vuex.Store({ 16 | modules: { 17 | app, 18 | user, 19 | routes, 20 | notice, 21 | company 22 | }, 23 | state: { 24 | windowWidth: 800, 25 | windowHeight: 600, 26 | currentTime: 0, 27 | locale: 'zh' 28 | }, 29 | mutations: { 30 | SET_WINDOW_SIZE(state, { width, height }) { 31 | state.windowWidth = width 32 | state.windowHeight = height 33 | }, 34 | SET_TIME: (state, time) => { 35 | state.currentTime = time 36 | }, 37 | SET_LOCALE: (state, locale) => { 38 | state.locale = locale 39 | localStorage.setItem('ops_locale', locale) 40 | } 41 | }, 42 | actions: { 43 | setWindowSize({ commit }) { 44 | const width = window.innerWidth 45 | const height = window.innerHeight 46 | commit('SET_WINDOW_SIZE', { width, height }) 47 | }, 48 | setTime: ({ commit }, time) => { 49 | commit('SET_TIME', time) 50 | } 51 | }, 52 | getters 53 | }) 54 | 55 | appConfig.buildModules.forEach(appName => { 56 | import(`@/modules/${appName}/index.js`).then(m => { 57 | if (m.default.store) { 58 | store.registerModule(m.default.store.name || m.deault.name, m.default.store) 59 | } 60 | }) 61 | }) 62 | 63 | export default store 64 | -------------------------------------------------------------------------------- /cmdb-ui/src/style/index.css: -------------------------------------------------------------------------------- 1 | ::-webkit-scrollbar { 2 | width: 8px; 3 | height: 8px; 4 | } 5 | 6 | ::-webkit-scrollbar-track { 7 | width: 8px; 8 | background-color: rgba(217, 217, 217, 0.2); 9 | box-shadow: inset 0px 4px 4px rgba(0, 0, 0, 0.1); 10 | border-radius: 5px; 11 | } 12 | 13 | ::-webkit-scrollbar-thumb { 14 | background-color: rgba(47, 122, 235, 0.2); 15 | background-clip: padding-box; 16 | border-radius: 5px; 17 | } 18 | 19 | ::-webkit-scrollbar-thumb:hover { 20 | background-color: rgba(47, 122, 235, 0.2); 21 | } 22 | 23 | /*# sourceMappingURL=index.css.map */ -------------------------------------------------------------------------------- /cmdb-ui/src/style/index.less: -------------------------------------------------------------------------------- 1 | @import "./global.less"; 2 | -------------------------------------------------------------------------------- /cmdb-ui/src/utils/axios.js: -------------------------------------------------------------------------------- 1 | const VueAxios = { 2 | vm: {}, 3 | // eslint-disable-next-line no-unused-vars 4 | install(Vue, instance) { 5 | if (this.installed) { 6 | return 7 | } 8 | this.installed = true 9 | 10 | if (!instance) { 11 | // eslint-disable-next-line no-console 12 | console.error('You have to install axios') 13 | return 14 | } 15 | 16 | Vue.axios = instance 17 | Object.defineProperties(Vue.prototype, { 18 | axios: { 19 | get: function get() { 20 | return instance 21 | } 22 | }, 23 | $http: { 24 | get: function get() { 25 | return instance 26 | } 27 | } 28 | }) 29 | } 30 | } 31 | 32 | export { 33 | VueAxios 34 | } 35 | -------------------------------------------------------------------------------- /cmdb-ui/src/utils/device.js: -------------------------------------------------------------------------------- 1 | import enquireJs from 'enquire.js' 2 | 3 | export const DEVICE_TYPE = { 4 | DESKTOP: 'desktop', 5 | TABLET: 'tablet', 6 | MOBILE: 'mobile' 7 | } 8 | 9 | export const deviceEnquire = function (callback) { 10 | const matchDesktop = { 11 | match: () => { 12 | callback && callback(DEVICE_TYPE.DESKTOP) 13 | } 14 | } 15 | 16 | const matchLablet = { 17 | match: () => { 18 | callback && callback(DEVICE_TYPE.TABLET) 19 | } 20 | } 21 | 22 | const matchMobile = { 23 | match: () => { 24 | callback && callback(DEVICE_TYPE.MOBILE) 25 | } 26 | } 27 | 28 | // screen and (max-width: 1087.99px) 29 | enquireJs 30 | .register('screen and (max-width: 576px)', matchMobile) 31 | .register('screen and (min-width: 576px) and (max-width: 1199px)', matchLablet) 32 | .register('screen and (min-width: 1200px)', matchDesktop) 33 | } 34 | -------------------------------------------------------------------------------- /cmdb-ui/src/utils/domUtil.js: -------------------------------------------------------------------------------- 1 | export const setDocumentTitle = function (title) { 2 | document.title = title 3 | const ua = navigator.userAgent 4 | // eslint-disable-next-line 5 | const regex = /\bMicroMessenger\/([\d\.]+)/ 6 | if (regex.test(ua) && /ip(hone|od|ad)/i.test(ua)) { 7 | const i = document.createElement('iframe') 8 | i.src = '/favicon.ico' 9 | i.style.display = 'none' 10 | i.onload = function () { 11 | setTimeout(function () { 12 | i.remove() 13 | }, 9) 14 | } 15 | document.body.appendChild(i) 16 | } 17 | } 18 | 19 | export const domTitle = 'OneOps' 20 | -------------------------------------------------------------------------------- /cmdb-ui/src/utils/filter.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import moment from 'moment' 3 | import 'moment/locale/zh-cn' 4 | moment.locale('zh-cn') 5 | 6 | Vue.filter('NumberFormat', function (value) { 7 | return value.toLocaleString() 8 | }) 9 | 10 | Vue.filter('dayjs', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') { 11 | return moment(dataStr).format(pattern) 12 | }) 13 | 14 | Vue.filter('moment', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') { 15 | return moment(dataStr).format(pattern) 16 | }) 17 | -------------------------------------------------------------------------------- /cmdb-ui/src/utils/functions/set.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export function intersection(thisSet, otherSet) { 3 | //初始化一个新集合,用于表示交集。 4 | var interSectionSet = new Set() 5 | var values = Array.from(thisSet) 6 | for (var i = 0; i < values.length; i++) { 7 | 8 | if (otherSet.has(values[i])) { 9 | interSectionSet.add(values[i]) 10 | } 11 | } 12 | 13 | return interSectionSet 14 | } 15 | 16 | export function union(thisSet, otherSet) { 17 | var unionSet = new Set() 18 | var values = Array.from(thisSet) 19 | for (var i = 0; i < values.length; i++) { 20 | unionSet.add(values[i]) 21 | } 22 | values = Array.from(otherSet) 23 | for (var i = 0; i < values.length; i++) { 24 | unionSet.add(values[i]) 25 | } 26 | 27 | return unionSet 28 | } 29 | 30 | export function difference(thisSet, otherSet) { 31 | var differenceSet = new Set() 32 | var values = Array.from(thisSet) 33 | for (var i = 0; i < values.length; i++) { 34 | 35 | if (!otherSet.has(values[i])) { 36 | differenceSet.add(values[i]) 37 | } 38 | } 39 | 40 | return differenceSet 41 | } 42 | -------------------------------------------------------------------------------- /cmdb-ui/src/utils/helper/permission.js: -------------------------------------------------------------------------------- 1 | const PERMISSION_ENUM = { 2 | 'add': { key: 'add', label: '新增' }, 3 | 'delete': { key: 'delete', label: '删除' }, 4 | 'edit': { key: 'edit', label: '修改' }, 5 | 'query': { key: 'query', label: '查询' }, 6 | 'get': { key: 'get', label: '详情' }, 7 | 'enable': { key: 'enable', label: '启用' }, 8 | 'disable': { key: 'disable', label: '禁用' }, 9 | 'import': { key: 'import', label: '导入' }, 10 | 'export': { key: 'export', label: '导出' } 11 | } 12 | 13 | function plugin (Vue) { 14 | if (plugin.installed) { 15 | return 16 | } 17 | 18 | !Vue.prototype.$auth && Object.defineProperties(Vue.prototype, { 19 | $auth: { 20 | get () { 21 | const _this = this 22 | return (permissions) => { 23 | const [permission, action] = permissions.split('.') 24 | const permissionList = _this.$store.getters.roles.permissions 25 | return permissionList.find((val) => { 26 | return val.permissionId === permission 27 | }).actionList.findIndex((val) => { 28 | return val === action 29 | }) > -1 30 | } 31 | } 32 | } 33 | }) 34 | 35 | !Vue.prototype.$enum && Object.defineProperties(Vue.prototype, { 36 | $enum: { 37 | get () { 38 | // const _this = this; 39 | return (val) => { 40 | let result = PERMISSION_ENUM 41 | val && val.split('.').forEach(v => { 42 | result = result && result[v] || null 43 | }) 44 | return result 45 | } 46 | } 47 | } 48 | }) 49 | } 50 | 51 | export default plugin 52 | -------------------------------------------------------------------------------- /cmdb-ui/src/utils/utils.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/cmdb-ui/src/utils/utils.css -------------------------------------------------------------------------------- /cmdb-ui/src/utils/utils.less: -------------------------------------------------------------------------------- 1 | .textOverflow() { 2 | overflow: hidden; 3 | white-space: nowrap; 4 | text-overflow: ellipsis; 5 | word-break: break-all; 6 | } 7 | 8 | .textOverflowMulti(@line: 3, @bg: #fff) { 9 | position: relative; 10 | max-height: @line * 1.5em; 11 | margin-right: -1em; 12 | padding-right: 1em; 13 | overflow: hidden; 14 | line-height: 1.5em; 15 | text-align: justify; 16 | &::before { 17 | position: absolute; 18 | right: 14px; 19 | bottom: 0; 20 | padding: 0 1px; 21 | background: @bg; 22 | content: '...'; 23 | } 24 | &::after { 25 | position: absolute; 26 | right: 14px; 27 | width: 1em; 28 | height: 1em; 29 | margin-top: 0.2em; 30 | background: white; 31 | content: ''; 32 | } 33 | } 34 | 35 | // mixins for clearfix 36 | // ------------------------ 37 | .clearfix() { 38 | zoom: 1; 39 | &::before, 40 | &::after { 41 | display: table; 42 | content: ' '; 43 | } 44 | &::after { 45 | clear: both; 46 | height: 0; 47 | font-size: 0; 48 | visibility: hidden; 49 | } 50 | } -------------------------------------------------------------------------------- /cmdb-ui/src/views/exception/403.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 14 | 15 | 18 | -------------------------------------------------------------------------------- /cmdb-ui/src/views/exception/404.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 14 | 15 | 18 | -------------------------------------------------------------------------------- /cmdb-ui/src/views/exception/500.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 14 | 15 | 18 | -------------------------------------------------------------------------------- /cmdb-ui/src/views/setting/auth/loginModal.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /cmdb-ui/src/views/setting/companyStructure/eventBus/bus.js: -------------------------------------------------------------------------------- 1 | // 用于树状递归组件的通信 2 | import Vue from 'vue' 3 | export default new Vue() 4 | -------------------------------------------------------------------------------- /cmdb-ui/src/views/setting/components/relateEmployee.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /cmdb-ui/src/views/setting/components/settingFilterComp/constants.js: -------------------------------------------------------------------------------- 1 | import i18n from '@/lang' 2 | 3 | export const ruleTypeList = [ 4 | { value: '&', label: i18n.t('cs.components.and') }, 5 | { value: '|', label: i18n.t('cs.components.or') }, 6 | // { value: 'not', label: '非' }, 7 | ] 8 | 9 | export const expList = [ 10 | { value: 1, label: i18n.t('cs.components.equal') }, 11 | { value: 2, label: i18n.t('cs.components.notEqual') }, 12 | // { value: 'contain', label: '包含' }, 13 | // { value: '~contain', label: '不包含' }, 14 | // { value: 'start_with', label: '以...开始' }, 15 | // { value: '~start_with', label: '不以...开始' }, 16 | // { value: 'end_with', label: '以...结束' }, 17 | // { value: '~end_with', label: '不以...结束' }, 18 | { value: 7, label: i18n.t('cs.components.isEmpty') }, // 为空的定义有点绕 19 | { value: 8, label: i18n.t('cs.components.isNotEmpty') }, 20 | ] 21 | 22 | export const advancedExpList = [ 23 | // { value: 'in', label: 'in查询' }, 24 | // { value: '~in', label: '非in查询' }, 25 | // { value: 'range', label: '范围' }, 26 | // { value: '~range', label: '范围外' }, 27 | { value: 'compare', label: i18n.t('cs.components.compare') }, 28 | ] 29 | 30 | export const compareTypeList = [ 31 | { value: 5, label: i18n.t('cs.components.moreThan') }, 32 | // { value: '2', label: '>=' }, 33 | { value: 6, label: i18n.t('cs.components.lessThan') }, 34 | // { value: '4', label: '<=' }, 35 | ] 36 | -------------------------------------------------------------------------------- /cmdb-ui/src/views/setting/components/spanTitle.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 20 | 21 | 32 | -------------------------------------------------------------------------------- /cmdb-ui/src/views/setting/notice/email/index.less: -------------------------------------------------------------------------------- 1 | .notice-email-wrapper { 2 | background-color: #fff; 3 | overflow: auto; 4 | .notice-email-error-tips { 5 | display: inline-block; 6 | background-color: #ffdfdf; 7 | border-radius: 4px; 8 | padding: 0 12px; 9 | width: 300px; 10 | color: #000000; 11 | margin-top: 8px; 12 | } 13 | .ant-form-item { 14 | margin-bottom: 10px; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /cmdb-ui/src/views/setting/notice/email/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 32 | 33 | 44 | -------------------------------------------------------------------------------- /cmdb-ui/src/views/user/RegisterResult.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 47 | 48 | 51 | -------------------------------------------------------------------------------- /cmdb-ui/webstorm.config.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | 4 | function resolve (dir) { 5 | return path.join(__dirname, '.', dir) 6 | } 7 | 8 | module.exports = { 9 | context: path.resolve(__dirname, './'), 10 | resolve: { 11 | extensions: ['.js', '.vue', '.json'], 12 | alias: { 13 | '@': resolve('src') 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /docker/Dockerfile-API: -------------------------------------------------------------------------------- 1 | # ================================= API ================================ 2 | FROM python:3.8-alpine AS cmdb-api 3 | 4 | LABEL description="Python3.8,cmdb" 5 | 6 | COPY cmdb-api /data/apps/cmdb 7 | 8 | WORKDIR /data/apps/cmdb 9 | 10 | RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories 11 | 12 | RUN apk add --no-cache tzdata gcc musl-dev libffi-dev openldap-dev python3-dev jpeg-dev zlib-dev build-base 13 | 14 | ENV TZ=Asia/Shanghai 15 | 16 | RUN pip install --no-cache-dir -r requirements.txt \ 17 | && cp ./settings.example.py settings.py \ 18 | && sed -i "s#{user}:{password}@127.0.0.1:3306/{db}#cmdb:123456@mysql:3306/cmdb#g" settings.py \ 19 | && sed -i "s#redis://127.0.0.1#redis://redis#g" settings.py \ 20 | && sed -i "s#CACHE_REDIS_HOST = '127.0.0.1'#CACHE_REDIS_HOST = 'redis'#g" settings.py 21 | 22 | ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.7.3/wait /wait 23 | RUN chmod +x /wait 24 | 25 | CMD ["bash", "-c", "flask run"] -------------------------------------------------------------------------------- /docker/Dockerfile-UI: -------------------------------------------------------------------------------- 1 | # ================================= UI ================================ 2 | FROM node:16.20 AS builder 3 | 4 | LABEL description="cmdb-ui" 5 | 6 | COPY cmdb-ui /data/apps/cmdb-ui 7 | 8 | WORKDIR /data/apps/cmdb-ui 9 | 10 | RUN sed -i "s#http://127.0.0.1:5000##g" .env && yarn install --ignore-engines --network-timeout 1000000 && yarn build 11 | 12 | FROM nginx:alpine AS cmdb-ui 13 | 14 | RUN mkdir /etc/nginx/html && rm -f /etc/nginx/conf.d/default.conf 15 | 16 | COPY --from=builder /data/apps/cmdb-ui/dist /etc/nginx/html/ 17 | -------------------------------------------------------------------------------- /docs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # 🎉 Contributing to CMDB 🥳 2 | 3 | 首先,非常感谢您考虑为我们的项目做出贡献!我们欢迎任何形式的贡献,无论是提出新功能、改进代码、修复 bug 还是改善文档。 4 | 5 | 本指南将为您提供所有相关信息,帮助您快速入门并开始参与本项目。请花几分钟阅读它,它将帮助我们更好地协作,共同创造一个更好的项目。 6 | 7 | ## ❖ 提交问题 (Issue) 8 | 9 | 在提交 PR 之前,请先搜索 现有的 [PR](https://github.com/veops/cmdb/pulls) 或 [Issue](https://github.com/veops/cmdb/issues),查看是否已经有相关的开放或关闭的提交。 10 | 11 | 如果是修复 bug,请首先提交一个 Issue。 12 | 13 | 对于新增功能,请先通过我们提供的联系方式与我们直接联系,以便更好的合作。 14 | 15 | ## ❖ 提交 PR 的步骤 16 | 17 | 1. 在 Github 上 fork 该项目的仓库。 18 | 2. 在本地复制仓库后创建一个新分支,用于开发新功能、修复 bug 或进行其他贡献,命令:`git checkout -b feat/xxxx`。 19 | 3. 提交您的更改:`git commit -am 'feat: add xxxxx'`。 20 | 4. 推送您的分支:`git push origin feat/xxxx`。 21 | 5. 提交 Pull Request 时,请确保您的源分支是刚刚推送的分支,目标分支是 CMDB 项目的 master 分支。 22 | 6. 提交后,请留意与 Pull Request 相关的邮件和通知。待通过审核后,我们会按计划将其合并到 master 分支,并进行新一轮的版本发布。 23 | 24 | ## ❖ 开发环境 25 | - Python 版本 >= 3.8 26 | - Node.js 版本 >= 14.17.6 27 | - Docker 28 | 29 | ## ❖ 代码风格 30 | 31 | **API**: 请遵循 [Python Style](https://google.github.io/styleguide/pyguide.html) 32 | 33 | **UI**: 请遵循 [node-style-guide](https://github.com/felixge/node-style-guide) 34 | 35 | ## ❖ 提交信息 36 | 37 | + 请遵循 [Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular) 38 | 39 | + 提交时使用不同的范围 40 | - API: `feat(api): xxx` 41 | - UI: `feat(ui): xxx` 42 | 43 | + 为了确保所有开发者都能更好地理解,提交信息请使用英文。 44 | 45 | - `feat` 添加新功能 46 | - `fix` 修复问题/BUG 47 | - `style` 代码风格相关,不影响运行结果 48 | - `perf` 优化/性能提升 49 | - `refactor` 代码重构 50 | - `revert` 撤销编辑 51 | - `test` 测试相关 52 | - `docs` 文档/注释 53 | - `chore` 依赖更新/脚手架配置修改等 54 | - `workflow` 工作流优化 55 | - `ci` 持续集成 56 | - `types` 类型定义文件变更 57 | - `wip` 开发中 58 | 59 | ## ❖ 代码内容 60 | 61 | 为了便于所有开发者理解,请确保代码注释和代码内容使用英文。 -------------------------------------------------------------------------------- /docs/flask-migrate.md: -------------------------------------------------------------------------------- 1 | ## 使用Flask-Migrate做数据库版本管理 2 | 3 | - 首次可以删除cmdb-api/migrations/versions下的所有文件 4 | - 5 | 6 | ### 进入cmdb-api完成下面步骤(操作可能会删除数据库中不被代码管理的表,如需保留请看文末中的tips) 7 | 8 | - 如果是首次使用需要先删除cmdb-api/migrations/versions下的所有文件(非首次跳过) 9 | - 执行`flask db migrate` 生成对应版本数据库表的升级文件到versions文件夹下,需要你的数据库是已经upgrade的 10 | - 执行`flask db upgrade` 数据库表同步更新到mysql 11 | 12 | 13 | ### tips 14 | 15 | - cmdb-api/migrations/env.py文件内的exclude_tables列表可以填写不想被flask-migrate管理的数据库表 16 | -------------------------------------------------------------------------------- /docs/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/docs/images/logo.png -------------------------------------------------------------------------------- /docs/images/qr_code.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/docs/images/qr_code.jpg -------------------------------------------------------------------------------- /docs/images/qrcode_for_gzh.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/docs/images/qrcode_for_gzh.jpg -------------------------------------------------------------------------------- /docs/images/view.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/docs/images/view.jpg -------------------------------------------------------------------------------- /docs/images/wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veops/cmdb/88df3355d88e343850c0306c5bbaaeaa768ff7bc/docs/images/wechat.png -------------------------------------------------------------------------------- /docs/makefile.md: -------------------------------------------------------------------------------- 1 | ## Install by Makefile 2 | 3 | - 启动 mysql 服务, redis 服务 4 | 5 | - 创建数据库 cmdb 6 | - 拉取代码 7 | 8 | ```bash 9 | git clone https://github.com/veops/cmdb.git 10 | cd cmdb 11 | cp cmdb-api/settings.example.py cmdb-api/settings.py 12 | ``` 13 | 14 | **设置 cmdb-api/settings.py 里的 database** 15 | 16 | - 顺序在 cmdb 目录下执行 17 | - 环境: `make env` 18 | - 启动 API: `make api` 19 | - 启动 UI: `make ui` 20 | - 启动 worker: `make worker` 21 | -------------------------------------------------------------------------------- /docs/makefile_en.md: -------------------------------------------------------------------------------- 1 | ### Install by Makefile 2 | 3 | - Start mysql,redis 4 | - Create mysql database: cmdb 5 | - Pull code 6 | 7 | ```bash 8 | git clone https://github.com/veops/cmdb.git 9 | cd cmdb 10 | cp cmdb-api/settings.example.py cmdb-api/settings.py 11 | ``` 12 | 13 | **set database in config file cmdb-api/settings.py** 14 | 15 | - In cmdb directory,start in order as follows: 16 | - environment: `make env` 17 | - start API: `make api` 18 | - start UI: `make ui` 19 | - start worker: `make worker` 20 | --------------------------------------------------------------------------------