From f731d5e6c164e42c53d3b8e6774c945f7b764115 Mon Sep 17 00:00:00 2001 From: wklken Date: Thu, 11 Apr 2019 18:23:44 +0800 Subject: [PATCH 01/12] Explain login/paas settings different between development/production (#79) * login settings SITE_URL diff in develoment/production * update doc: LOGIN_DOMAIN in paas development --- docs/install/ce_paas_install.md | 13 +++++++------ .../examples/settings/login/settings_production.py | 3 ++- .../examples/settings/paas/settings_production.py | 4 +++- paas-ce/paas/login/conf/settings_development.py | 1 + .../paas/login/conf/settings_production.py.sample | 3 ++- paas-ce/paas/paas/conf/settings_development.py | 5 ++++- .../paas/paas/conf/settings_production.py.sample | 4 +++- paas-ce/paas/paas/conf/settings_testing.py | 4 ++-- 8 files changed, 24 insertions(+), 13 deletions(-) diff --git a/docs/install/ce_paas_install.md b/docs/install/ce_paas_install.md index 285f5fb97..a8b455d48 100644 --- a/docs/install/ce_paas_install.md +++ b/docs/install/ce_paas_install.md @@ -84,7 +84,7 @@ $ cd paas-ce/paas/paas/ # 安装依赖 $ pip install -r requirements.txt -# 修改配置文件, 配置数据库,域名等 +# 修改配置文件, 配置数据库,域名等; 注意如果是本地开发需要配置 LOGIN_DOMAIN $ vim conf/settings_development.py # 注意, login / paas 务必要执行migrate @@ -115,9 +115,9 @@ esb/configs/default.py 配置文件注意事项: 1. 数据库配置: `HOST/PORT/USER/PASSWORD` -2. 涉及域名: 默认为`bking.com`, 如果自定义域名, 需修改4个配置文件中所有相关位置; `PAAS_DOMAIN`及`BK_COOKIE_DOMAIN` +2. 涉及域名: 默认为`www.bking.com`, 如果自定义域名, 需修改4个配置文件中所有相关位置; `PAAS_DOMAIN`及`BK_COOKIE_DOMAIN` 3. `SECRET_KEY` / `ESB_TOKEN`, 修改, 且4个文件这两个变量值保持一致 -4. `USERNAME` / `PASSWORD` 修改`login/settings_production.py`中初始化用户名密码, 超级管理员用户名密码, 建议强密码 +4. `USERNAME` / `PASSWORD` 修改`login/conf/settings_development.py`中初始化用户名密码, 超级管理员用户名密码, 建议强密码(注意, 生产环境中配置文件为`login/conf/settings_production.py`) 日志位置: 如果是`python manage.py runserver`拉起, 可以在终端看到请求日志 @@ -140,7 +140,7 @@ esb/logs/ #### 3. 访问 -假设配置`PAAS_DOMAIN`为`www.bking.com`, 部署机器IP为`127.0.0.1` +假设配置`PAAS_DOMAIN`为`www.bking.com:8001`, 部署机器IP为`127.0.0.1` 修改本地hosts @@ -150,7 +150,7 @@ esb/logs/ `http://www.bking.com:8001` 可以访问到开发者中心 -**注意** 登录用户名密码是`login/settings_production.py`中配置的 `USERNAME` / `PASSWORD` +**注意** 登录用户名密码是`login/conf/settings_development.py`中配置的 `USERNAME` / `PASSWORD` ---- @@ -175,6 +175,7 @@ esb/logs/ - 部署生产环境时, 需要设置环境变量`BK_ENV="production"`, 然后启动进程 - 生产的配置文件可以参考 `paas-ce/paas/examples/settings` -- 做`nginx`反向代理可以参考 `paas-ce/paas/examples/nginx_paas.conf` +- 做`nginx`反向代理可以参考 `paas-ce/paas/examples/nginx_paas.conf`; 注意如果使用nginx反向代理, 需确认 `login/conf/settings_*.py` 中 `SITE_URL = "/login/"`(否则登录页面静态资源404) - 使用`supervisord`托管可以参考 `paas-ce/paas/examples/supervisord.conf` - `PAAS_INNER_DOMAIN`及`HTTP_SCHEMA`是给全站https配置的, 当开启了https, 则配置这两个变量, 前者是paas的内网地址, 此时`PAAS_DOMAIN`为外网https地址 +- 登录用户名密码是`login/conf/settings_production.py`中配置的 `USERNAME` / `PASSWORD` diff --git a/paas-ce/paas/examples/settings/login/settings_production.py b/paas-ce/paas/examples/settings/login/settings_production.py index aae60c51c..e60dc6e73 100644 --- a/paas-ce/paas/examples/settings/login/settings_production.py +++ b/paas-ce/paas/examples/settings/login/settings_production.py @@ -15,7 +15,8 @@ if not DEBUG: STATIC_ROOT = 'static' -SITE_URL = "/" +# 生产环境, 使用nginx反向代理 /login/static/ +SITE_URL = "/login/" STATIC_URL = "/static/" diff --git a/paas-ce/paas/examples/settings/paas/settings_production.py b/paas-ce/paas/examples/settings/paas/settings_production.py index 5395c19ea..7a4a1d74a 100644 --- a/paas-ce/paas/examples/settings/paas/settings_production.py +++ b/paas-ce/paas/examples/settings/paas/settings_production.py @@ -29,7 +29,9 @@ } # domain -PAAS_DOMAIN = 'bking.com' +PAAS_DOMAIN = 'www.bking.com' +# 注意生产环境使用nginx反向代理不需要配置LOGIN_DOMAIN变量(删除即可) + # inner domain, use consul domain, for api PAAS_INNER_DOMAIN = '' HTTP_SCHEMA = 'http' diff --git a/paas-ce/paas/login/conf/settings_development.py b/paas-ce/paas/login/conf/settings_development.py index fb088f159..5531351c5 100644 --- a/paas-ce/paas/login/conf/settings_development.py +++ b/paas-ce/paas/login/conf/settings_development.py @@ -15,6 +15,7 @@ if not DEBUG: STATIC_ROOT = 'static' +# 本地开发登录页面静态资源, 注意: 生产环境使用nginx反向代理需要改成 SITE_URL = "/login/" SITE_URL = "/" STATIC_URL = "/static/" diff --git a/paas-ce/paas/login/conf/settings_production.py.sample b/paas-ce/paas/login/conf/settings_production.py.sample index aae60c51c..e60dc6e73 100644 --- a/paas-ce/paas/login/conf/settings_production.py.sample +++ b/paas-ce/paas/login/conf/settings_production.py.sample @@ -15,7 +15,8 @@ DEBUG = False if not DEBUG: STATIC_ROOT = 'static' -SITE_URL = "/" +# 生产环境, 使用nginx反向代理 /login/static/ +SITE_URL = "/login/" STATIC_URL = "/static/" diff --git a/paas-ce/paas/paas/conf/settings_development.py b/paas-ce/paas/paas/conf/settings_development.py index 2d9c1dbac..8cfda6612 100644 --- a/paas-ce/paas/paas/conf/settings_development.py +++ b/paas-ce/paas/paas/conf/settings_development.py @@ -29,7 +29,10 @@ } # domain -PAAS_DOMAIN = 'bking.com' +PAAS_DOMAIN = 'www.bking.com:8001' +# 跳转到本地开发使用的login服务, 仅本地开发用. 注意生产环境使用nginx反向代理不需要配置LOGIN_DOMAIN变量(删除即可) +LOGIN_DOMAIN = 'www.bking.com:8003' + # inner domain, use consul domain, for api PAAS_INNER_DOMAIN = '' HTTP_SCHEMA = 'http' diff --git a/paas-ce/paas/paas/conf/settings_production.py.sample b/paas-ce/paas/paas/conf/settings_production.py.sample index 5395c19ea..7a4a1d74a 100644 --- a/paas-ce/paas/paas/conf/settings_production.py.sample +++ b/paas-ce/paas/paas/conf/settings_production.py.sample @@ -29,7 +29,9 @@ DATABASES = { } # domain -PAAS_DOMAIN = 'bking.com' +PAAS_DOMAIN = 'www.bking.com' +# 注意生产环境使用nginx反向代理不需要配置LOGIN_DOMAIN变量(删除即可) + # inner domain, use consul domain, for api PAAS_INNER_DOMAIN = '' HTTP_SCHEMA = 'http' diff --git a/paas-ce/paas/paas/conf/settings_testing.py b/paas-ce/paas/paas/conf/settings_testing.py index 34cdf9765..971281d40 100644 --- a/paas-ce/paas/paas/conf/settings_testing.py +++ b/paas-ce/paas/paas/conf/settings_testing.py @@ -25,9 +25,9 @@ } # domain -PAAS_DOMAIN = 'bking.com' +PAAS_DOMAIN = 'www.bking.com:8001' # inner domain, use consul domain, for api -PAAS_INNER_DOMAIN = 'bking.com' +PAAS_INNER_DOMAIN = '' HTTP_SCHEMA = 'http' From 5c82d879a85191a4987037ee1cac2983cee29f19 Mon Sep 17 00:00:00 2001 From: nannan00 <17491932+nannan00@users.noreply.github.com> Date: Thu, 11 Apr 2019 18:34:07 +0800 Subject: [PATCH 02/12] fix develop login url 404 (#81) --- paas-ce/paas/login/urls.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/paas-ce/paas/login/urls.py b/paas-ce/paas/login/urls.py index 97fe665b7..df92dde2b 100644 --- a/paas-ce/paas/login/urls.py +++ b/paas-ce/paas/login/urls.py @@ -32,7 +32,7 @@ from django.views import i18n as django_i18n_views -urlpatterns = [ +base_urlpatterns = [ # 登录页面 url(r'^$', views.LoginView.as_view()), url(r'^logout/$', views.LogoutView.as_view()), @@ -44,7 +44,12 @@ url(r'^api/v2/get_user/$', views_api_v2.UserView.as_view()), url(r'^api/v2/get_batch_users/$', views_api_v2.BatchUsersView.as_view()), url(r'^api/v2/get_all_users/$', views_api_v2.AllUsersView.as_view()), +] +urlpatterns = [ + url(r'^', include(base_urlpatterns)), + # 支持本地开发 + url(r'^login/', include(base_urlpatterns)), # 检查统一登录是否正常运行 url(r'^healthz/', include("healthz.urls")), # 反搜索 From 6569dace105f387c96f0941466d31eaa89af96e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A2=E5=85=88=E6=96=8C?= <6504967+xiexianbin@users.noreply.github.com> Date: Fri, 17 May 2019 17:03:20 +0800 Subject: [PATCH 03/12] =?UTF-8?q?bugfix:=20=E6=88=91=E7=9A=84=E5=BA=94?= =?UTF-8?q?=E7=94=A8-=E5=BA=94=E7=94=A8=E9=83=A8=E7=BD=B2-=E4=B8=8B?= =?UTF-8?q?=E6=9E=B6=20title=E9=94=99=E8=AF=AF=20(#94)=20(#117)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- paas-ce/paas/paas/templates/base_app.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paas-ce/paas/paas/templates/base_app.html b/paas-ce/paas/paas/templates/base_app.html index 9e7269bc7..29b93a19b 100644 --- a/paas-ce/paas/paas/templates/base_app.html +++ b/paas-ce/paas/paas/templates/base_app.html @@ -71,10 +71,10 @@ title_msg = u'基本信息管理' elif relative_path.startswith(SITE_URL + "release/history") or (relative_path.startswith(SITE_URL + "release/") and relative_path.endswith(SITE_URL + "version/")): title_msg = u'发布历史' - elif relative_path.startswith(SITE_URL + "release/"): - title_msg = u'发布部署' elif (relative_path.startswith(SITE_URL + "release/") and relative_path.endswith("offline/")): title_msg = u'下架' + elif relative_path.startswith(SITE_URL + "release/"): + title_msg = u'发布部署' %>
 
From 29756e62e5d0c6379c739733ff24385f73f712f9 Mon Sep 17 00:00:00 2001 From: wklken Date: Mon, 6 Jan 2020 10:24:06 +0800 Subject: [PATCH 04/12] Devops support (#167) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add python3 framework for resource download * add tag as extra field for api/v2/app_info * add bk_devops_nav logo * add is_display to app, for desktop * update py3 framework to 1.0.2 * add api for bk-sops light app * refactor : api for bk-sops light app * refactor 1: api for bk-sops light app * refactor 2: api for bk-sops light app * delete syncdb command for django version >= 1.9 * set requests default timeout 5 second and add some logs when exception * set HTTP_TIMEOUT variable in settings * add newline in settings_default.py * support py3 for esb sdk, update translation for some apis, support DELETE/PUT method for request some apis, support get bk apidoc from md files * up cc some apidocs * update VERSION to 3.2.3 * upgrade gunicorn to 19.9.0 * add guide for python3 framework * add app env var admin * update py3 framework to 1.0.3 * fix js pagination error * fix js pagination error * up cc confapis * Devops support fixbug20190306 (#14) * add error message where user info (phone, chname) check * fixbug: light app logo image name ramdom * refactor * up cc/sops apis * up cc/sops confapis * add try-except for bk_backend.authenticate (#15) * Bugfix 0311 (#16) * add try-except for bk_backend.authenticate * update bk_devops_nav logo * app.yml support app env init while setup (#17) * app.yml support app env init while setup * fix app env key/value validation for app.yml * env key/value type cast to str before validate * unify the app_env_var value length to 1000 * support old login account manage page url (#18) * remove on_migrate * add doc to release.md: update python framework to support https * update release.md * third server password should not be chinese * fix link too long text-overflow * fix some issues * remove header for some files * bugfix: bktoken decrypt wrong * batch issues fix * change version to 3.2.5 * modify default user logo (#51) * fix some icons display error (#52) * fix fta imap (#56) * Update release.md * fix the too complex of account _is_bk_token_valid (#59) * Explain login/paas settings different between development/production (#79) (#80) * login settings SITE_URL diff in develoment/production * update doc: LOGIN_DOMAIN in paas development * 修复本地开发登录URL 404问题 (#82) * fix develop login url 404 (#81) * 更新 sops 组件,更新cmsi 发送语音通知组件 (#84) * up sops confapis, cmsi send_voice_msg * add component conf for cmsi send_voice_msg * 更新release说明 (#85) * up sops confapis, cmsi send_voice_msg * add component conf for cmsi send_voice_msg * up release doc * fix login decrypt token code bug (#88) * paas_agent support python3 (#89) * fix sync blocking bug when build script times out (#64) * Upgrade python framework to 2.0.0 (#90) * upgrade python framework to 2.0.0 * change new framework icon * fix fta imap (#103) * Update weixin doc and fix ligth app logo (#105) * fix light app lose bug * update weixin notify doc * update weixin notify doc * fixbug: import user do not response bug * fix cc delete_object_attribute apidoc (#106) * update guide doc of python framework (#108) * bugfix: 滚动按钮提示内容错误。issue #97 (#113) * fixbug:Development Language Change #96 (#116) * add app-env title (#124) * add resource migration for python doc url and delete united dev-env (#129) * Add docker (#131) * add docker docs for quick experience * update docker support docs * update docker support docs * upgrade framework to 2.1.4.11 (#134) * update link or replace ce with open source version (#135) * 93:修改BUG:当版本历史为空时, 前端出现两条横线 (#123) * add static version for css/js (#136) * Fix user avatar (#142) * fix user avatar * add import_common_template for sops * Bugfix 0717 (#143) * fix #128; remove django specific version in document * fix #140; resource link to official website * use HTTP_SCHEMA for job/cc link int (#145) * update cc apis, add cmsi send_msg/get_msg_type (#146) * saas info show settings style (#150) * fix #147; add/delete user refresh list without query term (#149) * disable bk_language while the i18n is not support in ce (#155) * fix resource download icon (#156) * fix resource download icon * fix pep8 fail * fix login api ApiErrorCodeEnumV2 missing USER_NOT_EXISTS2 (#158) * support logo file in pkg root dir (#164) * Update docs (#166) * update readme.md/readme_en.md Co-authored-by: nannan00 <17491932+nannan00@users.noreply.github.com> Co-authored-by: jamesge Co-authored-by: alex-smile <443677891@qq.com> Co-authored-by: wenjaron <45757842+wenjaron@users.noreply.github.com> Co-authored-by: kindmaketheworldpeace <38469337+kindmaketheworldpeace@users.noreply.github.com> Co-authored-by: canway-obama <50621369+canway-obama@users.noreply.github.com> Co-authored-by: molly0755 <16878048@qq.com> --- VERSION | 2 +- docs/install/ce_paas_agent_install.md | 22 +- docs/resource/img/bk_paas_en.png | Bin 0 -> 24639 bytes docs/resource/img/bk_paas_zh.png | Bin 0 -> 33607 bytes docs/wiki/container-support.md | 79 + paas-ce/paas/VERSION | 2 +- paas-ce/paas/appengine/requirements.txt | 2 +- .../sdk_tmpl/blueking/component/base.py | 4 +- .../sdk_tmpl/blueking/component/client.py | 4 +- .../sdk_tmpl/blueking/component/compat.py | 26 + .../sdk_tmpl/blueking/component/utils.py | 10 +- paas-ce/paas/esb/common/base_loggers.py | 6 + paas-ce/paas/esb/common/base_utils.py | 29 +- paas-ce/paas/esb/common/constants.py | 9 +- paas-ce/paas/esb/common/errors.py | 2 +- .../components/bk/apis/bk_login/get_user.py | 8 + .../components/bk/apis/cc/toolkit/tools.py | 4 +- .../components/bk/apis/fta/toolkit/imap.py | 10 +- .../bk/apisv2/cc/bind_role_privilege.py | 2 +- .../bk/apisv2/cc/create_business.py | 2 +- .../esb/components/bk/apisv2/cc/create_set.py | 4 +- .../bk/apisv2/cc/get_host_base_info.py | 4 +- .../bk/apisv2/cc/search_biz_inst_topo.py | 12 +- .../bk/apisv2/cc/search_custom_query.py | 10 +- .../bk/apisv2/cc/search_inst_by_object.py | 10 +- .../components/bk/apisv2/cc/toolkit/tools.py | 21 +- .../bk/apisv2/cc/update_business.py | 2 +- .../components/bk/apisv2/cc/update_host.py | 4 +- .../components/bk/apisv2/cc/update_module.py | 2 +- .../apisv2/cc/update_object_topo_graphics.py | 2 +- .../esb/components/bk/apisv2/cc/update_set.py | 2 +- .../cc/apidocs/en/add_instance_association.md | 76 + .../cc/apidocs/en/bind_process_module.md | 36 + .../apidocs/en/delete_instance_association.md | 39 + .../apidocs/en/delete_process_module_bind.md | 38 + .../cc/apidocs/en/find_host_by_module.md | 153 ++ .../apidocs/en/find_instance_association.md | 88 ++ .../cc/apidocs/en/find_object_association.md | 98 ++ .../cc/apidocs/en/get_biz_internal_module.md | 54 + .../cc/apidocs/en/get_mainline_object_topo.md | 77 + .../cc/apidocs/en/get_operation_log.md | 4 +- .../cc/apidocs/en/get_process_bind_module.md | 65 + .../cc/apidocs/en/search_object_topo.md | 2 +- .../zh_hans/add_instance_association.md | 76 + .../cc/apidocs/zh_hans/bind_process_module.md | 37 + .../zh_hans/delete_instance_association.md | 39 + .../zh_hans/delete_object_attribute.md | 1 + .../zh_hans/delete_process_module_bind.md | 36 + .../cc/apidocs/zh_hans/find_host_by_module.md | 160 ++ .../zh_hans/find_instance_association.md | 90 ++ .../zh_hans/find_object_association.md | 100 ++ .../zh_hans/get_biz_internal_module.md | 64 + .../zh_hans/get_mainline_object_topo.md | 76 + .../zh_hans/get_process_bind_module.md | 67 + .../paas/esb/components/confapis/cc/cc.yaml | 186 ++- .../sops/apidocs/en/create_periodic_task.md | 16 +- .../confapis/sops/apidocs/en/create_task.md | 190 ++- .../sops/apidocs/en/get_periodic_task_info.md | 12 +- .../sops/apidocs/en/get_periodic_task_list.md | 7 +- .../sops/apidocs/en/get_task_detail.md | 333 +++++ .../sops/apidocs/en/get_task_node_detail.md | 132 ++ .../sops/apidocs/en/get_task_status.md | 7 +- .../sops/apidocs/en/get_template_info.md | 10 +- .../sops/apidocs/en/get_template_list.md | 10 +- .../sops/apidocs/en/import_common_template.md | 52 + .../en/modify_constants_for_periodic_task.md | 7 +- .../en/modify_cron_for_periodic_task.md | 9 +- .../confapis/sops/apidocs/en/node_callback.md | 49 + .../confapis/sops/apidocs/en/operate_task.md | 6 +- .../sops/apidocs/en/query_task_count.md | 4 +- .../apidocs/en/set_periodic_task_enabled.md | 8 +- .../confapis/sops/apidocs/en/start_task.md | 6 +- .../apidocs/zh_hans/create_periodic_task.md | 27 +- .../sops/apidocs/zh_hans/create_task.md | 188 ++- .../apidocs/zh_hans/get_periodic_task_info.md | 14 +- .../apidocs/zh_hans/get_periodic_task_list.md | 5 +- .../sops/apidocs/zh_hans/get_task_detail.md | 332 +++++ .../apidocs/zh_hans/get_task_node_detail.md | 132 ++ .../sops/apidocs/zh_hans/get_task_status.md | 7 +- .../sops/apidocs/zh_hans/get_template_info.md | 8 +- .../sops/apidocs/zh_hans/get_template_list.md | 8 +- .../apidocs/zh_hans/import_common_template.md | 52 + .../modify_constants_for_periodic_task.md | 10 +- .../zh_hans/modify_cron_for_periodic_task.md | 6 +- .../sops/apidocs/zh_hans/node_callback.md | 49 + .../sops/apidocs/zh_hans/operate_task.md | 4 +- .../sops/apidocs/zh_hans/query_task_count.md | 2 +- .../zh_hans/set_periodic_task_enabled.md | 4 +- .../sops/apidocs/zh_hans/start_task.md | 4 +- .../esb/components/confapis/sops/sops.yaml | 57 +- paas-ce/paas/esb/components/esb_conf.py | 16 + .../templates/cmsi/apidoc/noc_notice.js | 40 - .../templates/cmsi/apidocs/en/get_msg_type.md | 48 + .../templates/cmsi/apidocs/en/send_msg.md | 60 + .../cmsi/apidocs/zh_hans/get_msg_type.md | 48 + .../cmsi/apidocs/zh_hans/send_msg.md | 62 + .../generic/templates/cmsi/get_msg_type.py | 38 + .../generic/templates/cmsi/noc_notice.py | 142 -- .../generic/templates/cmsi/send_mail.py | 29 +- .../generic/templates/cmsi/send_msg.py | 76 + .../generic/templates/cmsi/send_sms.py | 3 - .../generic/templates/cmsi/send_voice_msg.py | 37 +- .../generic/templates/cmsi/send_weixin.py | 15 +- .../generic/templates/cmsi/toolkit/configs.py | 33 +- .../cmsi/toolkit/send_mail_with_smtp.py | 37 +- .../generic/templates/cmsi/toolkit/tools.py | 20 +- .../generic/templates/heartbeat/detect.py | 4 +- .../templates/qcloud_sms/send_multi_sms.py | 16 +- .../qcloud_sms/send_multi_sms_with_tpl.py | 18 +- .../generic/templates/qcloud_sms/send_sms.py | 16 +- .../templates/qcloud_sms/send_sms_with_tpl.py | 18 +- .../templates/qcloud_sms/toolkit/tools.py | 6 +- .../templates/qcloud_voice/__init__.py | 8 + .../templates/qcloud_voice/send_voice_msg.py | 78 + .../qcloud_voice/toolkit/__init__.py | 8 + .../templates/qcloud_voice/toolkit/configs.py | 20 + .../templates/qcloud_voice/toolkit/tools.py | 33 + paas-ce/paas/esb/esb/bkcore/models.py | 17 + paas-ce/paas/esb/esb/channel/base.py | 3 +- .../esb/management/commands/sync_api_docs.py | 62 +- .../paas/esb/esb/management/utils/api_docs.py | 13 +- .../esb/management/utils/component_tools.py | 49 +- paas-ce/paas/esb/esb/outgoing.py | 28 +- paas-ce/paas/esb/esb/utils/base.py | 3 +- paas-ce/paas/esb/esb/utils/confapis.py | 2 +- paas-ce/paas/esb/on_migrate | 11 - paas-ce/paas/esb/requirements.txt | 2 +- paas-ce/paas/login/bkaccount/accounts.py | 44 +- paas-ce/paas/login/bkaccount/constants.py | 5 +- paas-ce/paas/login/bkaccount/forms.py | 8 +- paas-ce/paas/login/bkaccount/urls.py | 4 + paas-ce/paas/login/conf/default.py | 2 +- .../login/locale/en/LC_MESSAGES/django.po | 1293 +++++++++-------- .../login/locale/en/LC_MESSAGES/djangojs.po | 432 +++--- .../locale/zh_Hans/LC_MESSAGES/django.po | 923 +++++------- .../locale/zh_Hans/LC_MESSAGES/djangojs.po | 432 +++--- paas-ce/paas/login/on_migrate | 8 - paas-ce/paas/login/requirements.txt | 2 +- paas-ce/paas/login/static/bk_user_import.xls | Bin 22016 -> 23040 bytes .../paas/login/static/bk_user_import_en.xls | Bin 22016 -> 22528 bytes .../paas/login/static/img/getadminheadimg.jpg | Bin 0 -> 11584 bytes paas-ce/paas/login/static/img/getheadimg.jpg | Bin 2300 -> 10913 bytes paas-ce/paas/login/static/js/users.js | 44 +- paas-ce/paas/login/static/js/users.min.js | 2 +- .../paas/login/templates/bkaccount/base.html | 7 +- .../login/templates/bkaccount/user_table.part | 4 +- .../paas/login/templates/bkaccount/users.html | 10 +- paas-ce/paas/paas/account/backends.py | 7 +- paas-ce/paas/paas/api/constants.py | 7 + paas-ce/paas/paas/api/forms.py | 133 ++ paas-ce/paas/paas/api/response.py | 34 + paas-ce/paas/paas/api/urls.py | 8 +- paas-ce/paas/paas/api/utils.py | 20 + paas-ce/paas/paas/api/views.py | 109 +- paas-ce/paas/paas/app/constants.py | 3 + paas-ce/paas/paas/app/forms.py | 9 +- paas-ce/paas/paas/app/manager.py | 13 +- .../app/migrations/0008_auto_20190124_1708.py | 37 + paas-ce/paas/paas/app/models.py | 25 +- paas-ce/paas/paas/app_env/admin.py | 17 +- paas-ce/paas/paas/app_env/forms.py | 4 +- paas-ce/paas/paas/app_env/manager.py | 35 + paas-ce/paas/paas/app_env/utils.py | 48 + paas-ce/paas/paas/common/utils.py | 4 +- .../paas/paas/esb/apps/api_docs/api_views.py | 5 +- paas-ce/paas/paas/esb/apps/api_docs/urls.py | 1 - paas-ce/paas/paas/esb/apps/api_docs/utils.py | 1 - paas-ce/paas/paas/esb/apps/api_docs/views.py | 1 - .../paas/esb/apps/bootstrapform/configs.py | 1 - .../bootstrapform/templatetags/bootstrap.py | 1 - .../en/hcp/get_host_list.py | 1 - .../en/hcp/toolkit/configs.py | 1 - .../zh-hans/hcp/get_host_list.py | 1 - .../zh-hans/hcp/toolkit/configs.py | 1 - .../mdfiles/zh-hans/weixin_component_guide.md | 63 +- paas-ce/paas/paas/esb/apps/guide/urls.py | 1 - paas-ce/paas/paas/esb/apps/guide/views.py | 1 - .../esb/apps/manager/buffet_comp/api_views.py | 4 - .../esb/apps/manager/buffet_comp/forms.py | 4 - .../esb/apps/manager/buffet_comp/views.py | 5 +- .../esb/apps/manager/channel/api_views.py | 1 - .../paas/esb/apps/manager/channel/forms.py | 1 - .../paas/esb/apps/manager/channel/views.py | 34 +- .../paas/paas/esb/apps/manager/index/views.py | 4 - .../paas/esb/apps/manager/system/api_views.py | 1 - .../paas/esb/apps/manager/system/forms.py | 1 - .../paas/esb/apps/manager/system/views.py | 4 - .../templates/manager/buffet_comp/list.html | 6 +- .../templates/manager/channel/edit.html | 2 +- .../templates/manager/channel/list.html | 16 +- .../manager/system/add_system_tmpl.html | 9 +- .../templates/manager/system/list.html | 13 +- paas-ce/paas/paas/esb/apps/manager/urls.py | 4 - paas-ce/paas/paas/esb/apps/manager/utils.py | 4 - paas-ce/paas/paas/esb/bkcore/admin.py | 1 - paas-ce/paas/paas/esb/bkcore/constants.py | 3 +- paas-ce/paas/paas/esb/bkcore/models.py | 21 +- paas-ce/paas/paas/esb/common/base_utils.py | 1 - paas-ce/paas/paas/esb/common/decorators.py | 1 - paas-ce/paas/paas/esb/configs/default.py | 4 +- paas-ce/paas/paas/esb/configs/urls.py | 1 - .../esb/mainsite/templates/mainsite/base.html | 6 +- paas-ce/paas/paas/home/constants.py | 6 +- paas-ce/paas/paas/home/manager.py | 8 +- paas-ce/paas/paas/home/models.py | 36 +- paas-ce/paas/paas/home/utils.py | 13 +- .../paas/paas/media/applogo/bk_devops_nav.png | Bin 0 -> 3324 bytes paas-ce/paas/paas/media/framework_py.tar.gz | Bin 0 -> 1131072 bytes paas-ce/paas/paas/on_migrate | 8 - paas-ce/paas/paas/requirements.txt | 2 +- .../0005_data_insert_framework_py3.py | 35 + .../migrations/0006_upgrade_framework.py | 42 + .../migrations/0007_update_python_doc_url.py | 30 + .../migrations/0008_upgrade_framework.py | 33 + paas-ce/paas/paas/saas/models.py | 4 +- paas-ce/paas/paas/saas/utils.py | 27 +- .../paas/static/esb/api_docs/css/search.css | 4 +- .../static/esb/api_docs/css/search.min.css | 2 +- .../paas/static/esb/api_docs/js/search.min.js | 7 + .../api_docs/js/system_api_docs_info.min.js | 7 + .../static/esb/api_docs/js/system_info.min.js | 7 + paas-ce/paas/paas/static/esb/css/base.css | 5 +- paas-ce/paas/paas/static/esb/css/base.min.css | 2 +- .../weixin_component_guide/15081252708641.jpg | Bin 159668 -> 199582 bytes .../paas/paas/static/esb/js/buffet_list.js | 4 +- .../paas/static/esb/js/buffet_list.min.js | 2 +- .../paas/paas/static/esb/js/channel_list.js | 2 +- .../paas/static/esb/js/channel_list.min.js | 2 +- .../paas/paas/static/esb/js/esb_add_system.js | 11 +- .../paas/static/esb/js/esb_add_system.min.js | 2 +- .../static/esb/utils/handlebars_helper.js | 7 + .../static/esb/utils/send_sample_request.js | 7 + paas-ce/paas/paas/static/home/css/index.css | 16 +- .../paas/paas/static/home/css/index.min.css | 2 +- .../paas/paas/static/img/getadminheadimg.jpg | Bin 0 -> 11584 bytes paas-ce/paas/paas/static/img/getheadimg.jpg | Bin 2300 -> 10913 bytes .../paas/static/img/resource/framework.png | Bin 7291 -> 6986 bytes .../paas/static/img/resource/framework_py.png | Bin 0 -> 6682 bytes .../static/img/resource/framework_py3.png | Bin 0 -> 6918 bytes .../paas/paas/static/js/paas_engine_third.js | 5 + .../paas/static/js/paas_engine_third.min.js | 2 +- .../paas/static/user_center/css/weixin.css | 1 - .../static/user_center/css/weixin.min.css | 2 +- paas-ce/paas/paas/templates/app/create.html | 2 +- .../paas/templates/app/create_detail.part | 6 +- paas-ce/paas/paas/templates/app/info.html | 6 +- paas-ce/paas/paas/templates/app/list.html | 4 +- .../paas/paas/templates/app/list_table.part | 2 +- paas-ce/paas/paas/templates/app_env/home.html | 5 +- paas-ce/paas/paas/templates/base.html | 9 +- paas-ce/paas/paas/templates/base_center.html | 9 +- .../templates/engine/external_server.html | 20 +- .../paas/paas/templates/engine/server.html | 2 +- paas-ce/paas/paas/templates/guide/newbie.html | 48 +- paas-ce/paas/paas/templates/home/index.html | 9 +- .../paas/paas/templates/release/version.html | 2 +- paas-ce/paas/paas/templates/saas/info.html | 6 +- paas-ce/paas/paas/templates/saas/list.html | 4 +- paas-ce/paas/release.md | 16 + paas-ce/paasagent/VERSION | 2 +- paas-ce/paasagent/etc/build/virtualenv/build | 74 +- .../etc/build/virtualenv/saas/buildsaas | 69 +- paas-ce/paasagent/job/job.go | 4 +- paas-ce/paasagent/release.md | 3 + README.md => readme.md | 40 +- README_EN.md => readme_en.md | 38 +- 266 files changed, 6940 insertions(+), 2590 deletions(-) create mode 100644 docs/resource/img/bk_paas_en.png create mode 100644 docs/resource/img/bk_paas_zh.png create mode 100644 docs/wiki/container-support.md create mode 100644 paas-ce/paas/esb/apps/sdk_management/sdk_tmpl/blueking/component/compat.py create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/en/add_instance_association.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/en/bind_process_module.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/en/delete_instance_association.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/en/delete_process_module_bind.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/en/find_host_by_module.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/en/find_instance_association.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/en/find_object_association.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/en/get_biz_internal_module.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/en/get_mainline_object_topo.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/en/get_process_bind_module.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/add_instance_association.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/bind_process_module.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/delete_instance_association.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/delete_process_module_bind.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/find_host_by_module.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/find_instance_association.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/find_object_association.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/get_biz_internal_module.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/get_mainline_object_topo.md create mode 100644 paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/get_process_bind_module.md create mode 100644 paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_task_detail.md create mode 100644 paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_task_node_detail.md create mode 100644 paas-ce/paas/esb/components/confapis/sops/apidocs/en/import_common_template.md create mode 100644 paas-ce/paas/esb/components/confapis/sops/apidocs/en/node_callback.md create mode 100644 paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_task_detail.md create mode 100644 paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_task_node_detail.md create mode 100644 paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/import_common_template.md create mode 100644 paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/node_callback.md delete mode 100644 paas-ce/paas/esb/components/generic/templates/cmsi/apidoc/noc_notice.js create mode 100644 paas-ce/paas/esb/components/generic/templates/cmsi/apidocs/en/get_msg_type.md create mode 100644 paas-ce/paas/esb/components/generic/templates/cmsi/apidocs/en/send_msg.md create mode 100644 paas-ce/paas/esb/components/generic/templates/cmsi/apidocs/zh_hans/get_msg_type.md create mode 100644 paas-ce/paas/esb/components/generic/templates/cmsi/apidocs/zh_hans/send_msg.md create mode 100644 paas-ce/paas/esb/components/generic/templates/cmsi/get_msg_type.py delete mode 100644 paas-ce/paas/esb/components/generic/templates/cmsi/noc_notice.py create mode 100644 paas-ce/paas/esb/components/generic/templates/cmsi/send_msg.py create mode 100644 paas-ce/paas/esb/components/generic/templates/qcloud_voice/__init__.py create mode 100644 paas-ce/paas/esb/components/generic/templates/qcloud_voice/send_voice_msg.py create mode 100644 paas-ce/paas/esb/components/generic/templates/qcloud_voice/toolkit/__init__.py create mode 100644 paas-ce/paas/esb/components/generic/templates/qcloud_voice/toolkit/configs.py create mode 100644 paas-ce/paas/esb/components/generic/templates/qcloud_voice/toolkit/tools.py delete mode 100755 paas-ce/paas/esb/on_migrate delete mode 100755 paas-ce/paas/login/on_migrate create mode 100644 paas-ce/paas/login/static/img/getadminheadimg.jpg mode change 100755 => 100644 paas-ce/paas/login/static/img/getheadimg.jpg create mode 100644 paas-ce/paas/paas/api/forms.py create mode 100644 paas-ce/paas/paas/api/response.py create mode 100644 paas-ce/paas/paas/api/utils.py create mode 100644 paas-ce/paas/paas/app/migrations/0008_auto_20190124_1708.py create mode 100644 paas-ce/paas/paas/app_env/utils.py create mode 100644 paas-ce/paas/paas/media/applogo/bk_devops_nav.png create mode 100644 paas-ce/paas/paas/media/framework_py.tar.gz delete mode 100755 paas-ce/paas/paas/on_migrate create mode 100644 paas-ce/paas/paas/resource/migrations/0005_data_insert_framework_py3.py create mode 100644 paas-ce/paas/paas/resource/migrations/0006_upgrade_framework.py create mode 100644 paas-ce/paas/paas/resource/migrations/0007_update_python_doc_url.py create mode 100644 paas-ce/paas/paas/resource/migrations/0008_upgrade_framework.py create mode 100644 paas-ce/paas/paas/static/img/getadminheadimg.jpg mode change 100755 => 100644 paas-ce/paas/paas/static/img/getheadimg.jpg create mode 100644 paas-ce/paas/paas/static/img/resource/framework_py.png create mode 100755 paas-ce/paas/paas/static/img/resource/framework_py3.png rename README.md => readme.md (57%) rename README_EN.md => readme_en.md (60%) diff --git a/VERSION b/VERSION index 8918e2bd9..47e5458f3 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ -PaaS 3.2.2 +PaaS 3.2.5 PaaSAgent 3.1.0 diff --git a/docs/install/ce_paas_agent_install.md b/docs/install/ce_paas_agent_install.md index 7258ba0dc..f38511de2 100644 --- a/docs/install/ce_paas_agent_install.md +++ b/docs/install/ce_paas_agent_install.md @@ -2,7 +2,7 @@ ## 系统要求 -- Python版本: python2.7 +- Python版本: python2.7/python3.6.7 - Go - Nginx - Linux环境 @@ -12,21 +12,33 @@ PaaSAgent需要部署在满足系统要求的app服务器上。建议最少准 #### 1. 基础环境初始化 -python 2.7环境初始化 +python 环境初始化 ``` # 确认基础python环境是python2.7 $ python --version Python 2.7.15 +# 执行以下命令确定python的安装路径 +$ which python + # 安装 virtualenv 及 预装包 $ pip install virtualenv virtualenvwrapper +$ pip install supervisor==3.3.3 $ pip install -r paas-ce/paasagent/etc/build/packages/requirements.txt -# 查看python路径 -$ which python +# 如果使用python3,建议将python3安装到/opt/py36目录下 +# 从源码包编译安装python3.6.7时,可能需要手动建立python和pip的软链 +$ cd /opt/py36/bin +$ ln -s python3.6 python +$ ln -s pip3 pip + +# 确认python3的版本 +$ /opt/py36/bin/python --version +Python 3.6.7 ``` + 构建目录及新建用户 ``` @@ -62,7 +74,7 @@ $ sed -i "s#TPL_AGENT_ROOT#${AGENT_ROOT}#g" paas_agent_config.yaml nginx/paasage $ chmod +x build/virtualenv/build build/virtualenv/saas/buildsaas ``` -注意: `build` 和 `buildsaas` 中的 `VIRTUALENVWRAPPER_PYTHON` 变量需要设置正确的 python 路径,默认`/usr/bin/python`, 如果上一步`which python`的返回结果不是`/usr/bin/python`, 需要修改为对应正确的路径 +注意: `build` 和 `buildsaas` 中的 `VIRTUALENVWRAPPER_PYTHON` 变量需要设置正确的 python 路径,默认`/usr/bin/python`, 如果上一步`which python`的返回结果不是`/usr/bin/python`, 需要修改为对应正确的路径;如果用到了python3,`PYTHON3_PATH`也需要设置成正确的路径,默认`/opt/py36` #### 3. 蓝鲸智云开发者中心注册服务器 diff --git a/docs/resource/img/bk_paas_en.png b/docs/resource/img/bk_paas_en.png new file mode 100644 index 0000000000000000000000000000000000000000..1556221e3ec9bf9d0732343519c0d52e2d288f02 GIT binary patch literal 24639 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 O-_ka^QE}ZV>VE*>JSq|Z literal 0 HcmV?d00001 diff --git a/docs/resource/img/bk_paas_zh.png b/docs/resource/img/bk_paas_zh.png new file mode 100644 index 0000000000000000000000000000000000000000..549100bd1d4b743aefaed1963906578948896fa2 GIT binary patch literal 33607 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" to HTML-safe sequences. + If the optional flag quote is true, the quotation mark character (") + is also translated. + rewrite the cgi method + @param html: html代码 + @param is_json: 是否为json串(True/False) ,默认为False + """ + # &转换 + if not is_json: + html = html.replace('&', '&') # Must be done first! + # <>转换 + html = html.replace("<", "<") + html = html.replace(">", ">") + # 单双引号转换 + if not is_json: + # html = html.replace(' ', " ") + html = html.replace('"', """) + html = html.replace("'", "'") + return html diff --git a/paas-ce/paas/esb/common/constants.py b/paas-ce/paas/esb/common/constants.py index 4d42ccdf7..a8b2b5c8b 100644 --- a/paas-ce/paas/esb/common/constants.py +++ b/paas-ce/paas/esb/common/constants.py @@ -26,12 +26,17 @@ API_TYPE_OP = 'operate' API_TYPE_Q = 'query' +HTTP_METHOD = FancyDict(( + ('GET', 'GET'), + ('POST', 'POST'), +)) + BK_SYSTEMS = { 'BK_LOGIN': { 'name': 'BK_LOGIN', - 'label': _(u'蓝鲸登录平台'), - 'remark': u'蓝鲸登录平台,管理用户登录验证,及用户信息', + 'label': _(u'蓝鲸统一登录'), + 'remark': u'蓝鲸统一登录,管理用户登录验证,及用户信息', }, 'BK_PAAS': { 'name': 'BK_PAAS', diff --git a/paas-ce/paas/esb/common/errors.py b/paas-ce/paas/esb/common/errors.py index cd12205e2..efca2e2cd 100644 --- a/paas-ce/paas/esb/common/errors.py +++ b/paas-ce/paas/esb/common/errors.py @@ -144,7 +144,7 @@ class ErrorCodes(object): """ error_codes = ( - # 13063xx, user error + # 13064xx, user error ErrorCode('OPERATOR_REQUIRED', 1306401, 'You must specify the current operator'), ErrorCode('USER_PERMISSION_DENIED', 1306402, 'User permission is insufficient'), ErrorCode('APP_PERMISSION_DENIED', 1306403, 'APP permission is insufficient'), diff --git a/paas-ce/paas/esb/components/bk/apis/bk_login/get_user.py b/paas-ce/paas/esb/components/bk/apis/bk_login/get_user.py index 6f40c5672..bc8a47f71 100644 --- a/paas-ce/paas/esb/components/bk/apis/bk_login/get_user.py +++ b/paas-ce/paas/esb/components/bk/apis/bk_login/get_user.py @@ -71,6 +71,14 @@ class GetUser(Component): class Form(BaseComponentForm): bk_token = forms.CharField(label='login token', required=False) username = forms.CharField(label='username', required=False) + bk_username = forms.CharField(label='bk_username', required=False) + + def clean(self): + data = self.cleaned_data + return { + 'bk_token': data['bk_token'], + 'username': data['username'] or data['bk_username'], + } def handle(self): self.response.payload = self.outgoing.http_client.get( diff --git a/paas-ce/paas/esb/components/bk/apis/cc/toolkit/tools.py b/paas-ce/paas/esb/components/bk/apis/cc/toolkit/tools.py index 221d5c054..332588adb 100644 --- a/paas-ce/paas/esb/components/bk/apis/cc/toolkit/tools.py +++ b/paas-ce/paas/esb/components/bk/apis/cc/toolkit/tools.py @@ -45,8 +45,8 @@ def post_request(self, host, path, data=None, headers_json=True, **kwargs): except Exception: logger.exception('response: %s', response) raise CommonAPIError( - 'An exception occurred while requesting CC interface, ' - 'please contact the component developer to handle it.') + 'An error occurred while requesting CC interface, ' + 'the response content does not contain code field.') if code != '0': return { diff --git a/paas-ce/paas/esb/components/bk/apis/fta/toolkit/imap.py b/paas-ce/paas/esb/components/bk/apis/fta/toolkit/imap.py index 3b59ce9de..536a857ff 100644 --- a/paas-ce/paas/esb/components/bk/apis/fta/toolkit/imap.py +++ b/paas-ce/paas/esb/components/bk/apis/fta/toolkit/imap.py @@ -174,12 +174,15 @@ def search(self, charset=None, unseen=None, before=None, since=None, size_limit= def filter(self, mails, sent_from=None, sent_to=None, subject=None, before=None, since=None, fetch_header_already=False): result_list = [] - mails = mails if fetch_header_already else self.iter_fetch_chunks(mails=mails, criteria=self.CRITERIA_HEADER,) + mails = mails + if not fetch_header_already: + for index in range(0, len(mails)): + self.fetch_header(mails[index * 100:(index + 1) * 100]) sent_from = sent_from.split(",") if sent_from else () sent_to = sent_to.split(",") if sent_to else () subject = [subject] if subject else [] for mail in mails: - if ((before and before <= mail.time) or (since and since > mail.time)): + if mail.time is None or (before and before <= mail.time) or (since and since > mail.time): continue if sent_from and not contain_one(mail.sender, sent_from): continue @@ -187,7 +190,6 @@ def filter(self, mails, sent_from=None, sent_to=None, subject=None, before=None, continue if subject and not contain_one(mail.subject, subject): continue - result_list.append(mail) return result_list @@ -197,7 +199,7 @@ def fetch_header(self, mails): def fetch(self, mails, criteria=None): mail_mappings = {str(mail.uid): mail for mail in mails} - status, result = self.imap_client.fetch(",".join(mail_mappings.keys()), criteria or self.CRITERIA,) + status, result = self.imap_client.fetch(",".join(mail_mappings.keys()), criteria or self.CRITERIA) if status != "OK": raise Exception("fetch mail[%s] failed", mail_mappings.keys()) diff --git a/paas-ce/paas/esb/components/bk/apisv2/cc/bind_role_privilege.py b/paas-ce/paas/esb/components/bk/apisv2/cc/bind_role_privilege.py index a45604fa2..73e1f1041 100644 --- a/paas-ce/paas/esb/components/bk/apisv2/cc/bind_role_privilege.py +++ b/paas-ce/paas/esb/components/bk/apisv2/cc/bind_role_privilege.py @@ -33,7 +33,7 @@ class BindRolePrivilege(Component): | {{ _("字段") }} | {{ _("类型") }} | {{ _("必选") }} | {{ _("描述") }} | |-----------|------------|--------|------------| - | bk_supplier_account | string | {{ _("是") }} | {{ _("开发商帐号") }} | + | bk_supplier_account | string | {{ _("是") }} | {{ _("开发商账号") }} | | bk_obj_id | string | {{ _("是") }} | {{ _("模型ID") }} | | bk_property_id | string | {{ _("是") }} | {{ _("模型对应用户角色属性ID") }} | | data | list | {{ _("否") }} | {{ _("角色权限数据,输入为空数组则不绑定任何权限") }} | diff --git a/paas-ce/paas/esb/components/bk/apisv2/cc/create_business.py b/paas-ce/paas/esb/components/bk/apisv2/cc/create_business.py index bf48d77d8..6ee78b1aa 100644 --- a/paas-ce/paas/esb/components/bk/apisv2/cc/create_business.py +++ b/paas-ce/paas/esb/components/bk/apisv2/cc/create_business.py @@ -47,7 +47,7 @@ class CreateBusiness(Component): | bk_biz_tester | string | {{ _("是") }} | {{ _("测试人员") }} | | time_zone | string | {{ _("是") }} | {{ _("时区") }} | - **注意:此处的输入参数仅对必填以及系统内置的参数做了说明,其余需要填写的参数取决于用户自己定义的属性字段。** + **{{ _("注意:此处的输入参数仅对必填以及系统内置的参数做了说明,其余需要填写的参数取决于用户自己定义的属性字段") }}** ### {{ _("请求参数示例") }} diff --git a/paas-ce/paas/esb/components/bk/apisv2/cc/create_set.py b/paas-ce/paas/esb/components/bk/apisv2/cc/create_set.py index 721adeae9..01a7f0cff 100644 --- a/paas-ce/paas/esb/components/bk/apisv2/cc/create_set.py +++ b/paas-ce/paas/esb/components/bk/apisv2/cc/create_set.py @@ -41,11 +41,11 @@ class CreateSet(Component): | {{ _("字段") }} | {{ _("类型") }} | {{ _("必选") }} | {{ _("描述") }} | |-----------|------------|--------|------------| - | bk_parent_id | int | {{ _("是") }} | {{ _("父实例的ID") }} | + | bk_parent_id | int | {{ _("是") }} | {{ _("父节点的ID") }} | | bk_set_name | string | {{ _("是") }} | {{ _("集群名字") }} | | default | int | {{ _("否") }} | {{ _("0-普通集群,1-内置模块集合,默认为0") }} | - **注意:其它需要的字段由模型定义** + **{{ _("注意:其它需要的字段由模型定义") }}** ### {{ _("请求参数示例") }} diff --git a/paas-ce/paas/esb/components/bk/apisv2/cc/get_host_base_info.py b/paas-ce/paas/esb/components/bk/apisv2/cc/get_host_base_info.py index 389dba1e8..7973beda9 100644 --- a/paas-ce/paas/esb/components/bk/apisv2/cc/get_host_base_info.py +++ b/paas-ce/paas/esb/components/bk/apisv2/cc/get_host_base_info.py @@ -57,12 +57,12 @@ class GetHostBaseInfo(Component): "data": [ { "bk_property_id": "bk_host_name", - "bk_property_name": "主机名", + "bk_property_name": "host name", "bk_property_value": "centos7" }, { "bk_property_id": "bk_host_id", - "bk_property_name": "主机ID", + "bk_property_name": "host ID", "bk_property_value": "10000" } ] diff --git a/paas-ce/paas/esb/components/bk/apisv2/cc/search_biz_inst_topo.py b/paas-ce/paas/esb/components/bk/apisv2/cc/search_biz_inst_topo.py index 37a177cf0..70b1576ad 100644 --- a/paas-ce/paas/esb/components/bk/apisv2/cc/search_biz_inst_topo.py +++ b/paas-ce/paas/esb/components/bk/apisv2/cc/search_biz_inst_topo.py @@ -31,7 +31,7 @@ class SearchBizInstTopo(Component): | {{ _("字段") }} | {{ _("类型") }} | {{ _("必选") }} | {{ _("描述") }} | |-----------|------------|--------|------------| - | bk_supplier_account | string | {{ _("否") }} | {{ _("开发商帐号") }} | + | bk_supplier_account | string | {{ _("否") }} | {{ _("开发商账号") }} | | bk_biz_id | int | {{ _("是") }} | {{ _("业务id") }} | | level | int | {{ _("否") }} | {{ _("拓扑的层级索引,索引取值从0开始,默认值为2,当设置为 -1 的时候会读取完整的业务实例拓扑") }} | @@ -57,21 +57,21 @@ class SearchBizInstTopo(Component): "data": [ { "bk_inst_id": 2, - "bk_inst_name": "蓝鲸", + "bk_inst_name": "blueking", "bk_obj_id": "biz", - "bk_obj_name": "业务", + "bk_obj_name": "business", "child": [ { "bk_inst_id": 3, - "bk_inst_name": "作业平台", + "bk_inst_name": "job", "bk_obj_id": "set", - "bk_obj_name": "集群", + "bk_obj_name": "set", "child": [ { "bk_inst_id": 5, "bk_inst_name": "job", "bk_obj_id": "module", - "bk_obj_name": "模块", + "bk_obj_name": "module", "child": [] } ] diff --git a/paas-ce/paas/esb/components/bk/apisv2/cc/search_custom_query.py b/paas-ce/paas/esb/components/bk/apisv2/cc/search_custom_query.py index 813388ee0..915ca99d9 100644 --- a/paas-ce/paas/esb/components/bk/apisv2/cc/search_custom_query.py +++ b/paas-ce/paas/esb/components/bk/apisv2/cc/search_custom_query.py @@ -35,7 +35,7 @@ class SearchCustomQuery(Component): |-----------|------------|--------|------------| | bk_supplier_account | string | {{ _("否") }} | {{ _("开发商账号") }} | | bk_biz_id | int | {{ _("是") }} | {{ _("业务ID") }} | - | condition | dict | {{ _("是") }} | {{ _("查询条件,condition 字段为自定义api的属性字段, 可以是create_user,modify_user, name") }} | + | condition | dict | {{ _("否") }} | {{ _("查询条件,condition 字段为自定义api的属性字段, 可以是create_user,modify_user, name") }} | | start | int | {{ _("是") }} | {{ _("记录开始位置") }} | | limit | int | {{ _("是") }} | {{ _("每页限制条数,最大200") }} | @@ -128,7 +128,7 @@ class SearchCustomQuery(Component): class Form(BaseComponentForm): bk_biz_id = forms.IntegerField(label='business id', required=True) - condition = TypeCheckField(label='condition', promise_type=dict, required=True) + condition = TypeCheckField(label='condition', promise_type=dict, required=False) start = forms.IntegerField(label='start', required=True) limit = forms.IntegerField(label='limit', required=True) @@ -136,11 +136,7 @@ def clean(self): data = self.cleaned_data return { 'bk_biz_id': data['bk_biz_id'], - 'data': { - 'condition': data['condition'], - 'start': data['start'], - 'limit': data['limit'] - } + 'data': self.get_cleaned_data_when_exist(keys=['condition', 'start', 'limit']) } def handle(self): diff --git a/paas-ce/paas/esb/components/bk/apisv2/cc/search_inst_by_object.py b/paas-ce/paas/esb/components/bk/apisv2/cc/search_inst_by_object.py index 04ac3055f..e75f08959 100644 --- a/paas-ce/paas/esb/components/bk/apisv2/cc/search_inst_by_object.py +++ b/paas-ce/paas/esb/components/bk/apisv2/cc/search_inst_by_object.py @@ -33,7 +33,7 @@ class SearchInstByObject(Component): | {{ _("字段") }} | {{ _("类型") }} | {{ _("必选") }} | {{ _("描述") }} | |-----------|------------|--------|------------| - | bk_supplier_account | string | {{ _("否") }} | {{ _("开发商帐号") }} | + | bk_supplier_account | string | {{ _("否") }} | {{ _("开发商账号") }} | | bk_obj_id | string | {{ _("是") }} | {{ _("自定义模型ID,查询区域时为plat") }} | | fields | array | {{ _("否") }} | {{ _("指定查询的字段") }} | | condition | dict | {{ _("否") }} | {{ _("查询条件") }} | @@ -47,14 +47,14 @@ class SearchInstByObject(Component): | limit | int | {{ _("是") }} | {{ _("每页限制条数,最大200") }} | | sort | string | {{ _("否") }} | {{ _('排序字段') }} | - #### fields参数说明: + #### {{ _("fields参数说明") }} - 参数为查询的目标实例对应的模型定义的所有字段。 + {{ _("参数为查询的目标实例对应的模型定义的所有字段") }} - #### condition 参数说明: + #### {{ _("condition 参数说明") }} - condition 参数为查询的目标实例对应的模型定义的所有字段。 + {{ _("condition 参数为查询的目标实例对应的模型定义的所有字段") }} ### {{ _("请求参数示例") }} diff --git a/paas-ce/paas/esb/components/bk/apisv2/cc/toolkit/tools.py b/paas-ce/paas/esb/components/bk/apisv2/cc/toolkit/tools.py index 84f167dba..02871633b 100644 --- a/paas-ce/paas/esb/components/bk/apisv2/cc/toolkit/tools.py +++ b/paas-ce/paas/esb/components/bk/apisv2/cc/toolkit/tools.py @@ -9,7 +9,6 @@ import copy import json -from common.log import logger from common.errors import CommonAPIError from . import configs @@ -61,27 +60,25 @@ def format_response(self, response): return { 'result': False, 'code': 1306000, - 'message': 'Request interface error, response: %s' % response, + 'message': 'Request interface error, the response content is not a json string: %s' % response, } - try: - bk_error_code = response['bk_error_code'] - except Exception: - logger.exception('response: %s', response) - raise CommonAPIError( - 'An exception occurred while requesting CC interface, ' - 'please contact the component developer to handle it.') - if bk_error_code == 0: + bk_error_code = response.get('bk_error_code', response.get('code')) + if bk_error_code is None: + raise CommonAPIError( + 'An error occurred while requesting CC interface, ' + 'the response content does not contain bk_error_code field.') + elif bk_error_code == 0: return { 'result': True, 'code': 0, 'data': response.get('data'), - 'message': response.get('bk_error_msg') or '', + 'message': response.get('bk_error_msg', response.get('message')) or '', } else: return { 'result': False, 'code': bk_error_code, 'data': response.get('data'), - 'message': response.get('bk_error_msg') or '', + 'message': response.get('bk_error_msg', response.get('message')) or '', } diff --git a/paas-ce/paas/esb/components/bk/apisv2/cc/update_business.py b/paas-ce/paas/esb/components/bk/apisv2/cc/update_business.py index d52a15556..07d67a221 100644 --- a/paas-ce/paas/esb/components/bk/apisv2/cc/update_business.py +++ b/paas-ce/paas/esb/components/bk/apisv2/cc/update_business.py @@ -47,7 +47,7 @@ class UpdateBusiness(Component): | bk_biz_productor | string | {{ _("否") }} | {{ _("产品人员") }} | | bk_biz_tester | string | {{ _("否") }} | {{ _("测试人员") }} | - **注意:此处的输入参数仅对必填以及系统内置的参数做了说明,其余需要填写的参数取决于用户自己定义的属性字段** + **{{ _("注意:此处的输入参数仅对必填以及系统内置的参数做了说明,其余需要填写的参数取决于用户自己定义的属性字段") }}** ### {{ _("请求参数示例") }} diff --git a/paas-ce/paas/esb/components/bk/apisv2/cc/update_host.py b/paas-ce/paas/esb/components/bk/apisv2/cc/update_host.py index 8267dfb6e..1e16d5496 100644 --- a/paas-ce/paas/esb/components/bk/apisv2/cc/update_host.py +++ b/paas-ce/paas/esb/components/bk/apisv2/cc/update_host.py @@ -41,7 +41,7 @@ class UpdateHost(Component): |-----------|------------|--------|------------| | bk_host_name | string | {{ _("否") }} | {{ _("主机名") }} | - **注意:输入的字段为主机定义的属性** + **{{ _("注意:输入的字段为主机定义的属性") }}** ### {{ _("请求参数示例") }} @@ -82,7 +82,7 @@ class Form(BaseComponentForm): def clean(self): data = self.cleaned_data - data['data'].update(bk_host_id=','.join(data['bk_host_id'])) + data['data'].update(bk_host_id=','.join(map(str, data['bk_host_id']))) return data['data'] def handle(self): diff --git a/paas-ce/paas/esb/components/bk/apisv2/cc/update_module.py b/paas-ce/paas/esb/components/bk/apisv2/cc/update_module.py index 07729777f..245122f21 100644 --- a/paas-ce/paas/esb/components/bk/apisv2/cc/update_module.py +++ b/paas-ce/paas/esb/components/bk/apisv2/cc/update_module.py @@ -45,7 +45,7 @@ class UpdateModule(Component): |-----------|------------|--------|------------| | bk_module_name | string | {{ _("否") }} | {{ _("模块名") }} | - **注意:输入的字段为模块定义的属性** + **{{ _("注意:输入的字段为模块定义的属性") }}** ### {{ _("请求参数示例") }} diff --git a/paas-ce/paas/esb/components/bk/apisv2/cc/update_object_topo_graphics.py b/paas-ce/paas/esb/components/bk/apisv2/cc/update_object_topo_graphics.py index dab01a365..3cd3be9ad 100644 --- a/paas-ce/paas/esb/components/bk/apisv2/cc/update_object_topo_graphics.py +++ b/paas-ce/paas/esb/components/bk/apisv2/cc/update_object_topo_graphics.py @@ -51,7 +51,7 @@ class UpdateObjectTopoGraphics(Component): | bk_obj_icon | string | {{ _("否") }} | {{ _("对象模型的图标") }} | - **注意**: + **{{ _("注意") }}**: - {{ _("scope_type,scope_id 唯一确定一张图") }} diff --git a/paas-ce/paas/esb/components/bk/apisv2/cc/update_set.py b/paas-ce/paas/esb/components/bk/apisv2/cc/update_set.py index 5194c51d3..f202a71e0 100644 --- a/paas-ce/paas/esb/components/bk/apisv2/cc/update_set.py +++ b/paas-ce/paas/esb/components/bk/apisv2/cc/update_set.py @@ -45,7 +45,7 @@ class UpdateSet(Component): | bk_parent_id | int | {{ _("否") }} | {{ _("父节点的ID") }} | | bk_set_name | string | {{ _("否") }} | {{ _("集群名字") }} | - **注意:用户自定义的字段也可以作为参数传入** + **{{ _("注意:用户自定义的字段也可以作为参数传入") }}** ### {{ _("请求参数示例") }} diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/en/add_instance_association.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/add_instance_association.md new file mode 100644 index 000000000..4c15fa392 --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/add_instance_association.md @@ -0,0 +1,76 @@ +### Functional description + +create association between object's instance. + +### Request Parameters + +{{ common_args_desc }} + +#### General Parameters + +| Field | Type | Required | Description | +|----------------------|------------|--------|-----------------------------| +| metadata | object | Yes | request meta data | +| condition | string map | Yes | query condition | + + +metadata params + +| Field | Type | Required | Description | +|---------------------|------------|--------|-----------------------------| +| label | string map | Yes |the label data request should with, such as biz info | + + +label params + +| Field | Type | Required | Description | +|---------------------|------------|--------|-----------------------------| +| bk_biz_id | string | Yes | business's ID | + + +condition params + +| Field | Type | Required | Description | +|---------------------|------------|--------|-----------------------------| +| bk_obj_asst_id | string | Yes | object's association unique id | +| bk_inst_id | int64 | Yes | association's source object's instance id | +| bk_asst_inst_id | int64 | Yes | association's destination object's instance id | + + +### Request Parameters Example + +``` json +{ + "bk_obj_asst_id": "bk_switch_belong_bk_host", + "bk_inst_id": 11, + "bk_asst_inst_id": 21, + "metadata":{ + "label":{ + "bk_biz_id":"1" + } + } +} +``` + +### Return Result Example + +```json +{ + "result": true, + "code": 0, + "message": "", + "data": { + "id": 1038 + } +} + +``` + +### Return Result Parameters Description + +#### data : + +| Field | Type | Description | +|------------|----------|--------------| +|id|int64|the instance association's unique id| + diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/en/bind_process_module.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/bind_process_module.md new file mode 100644 index 000000000..79047f390 --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/bind_process_module.md @@ -0,0 +1,36 @@ +### Functional description + +bind process to module + +### Request Parameters + +{{ common_args_desc }} + +#### General Parameters + +| Field | Type | Required | Description | +|------------|----------|--------|---------------| +| bk_supplier_account | string | Yes | Supplier account | +| bk_biz_id | int | string | Bussiness ID | +| bk_process_id | int | string | Process ID | +| bk_module_name | string | string | Module Name | + + +### Request Parameters Example + +```python + +``` + + +### Return Result Example + +```python + +{ + "result": true, + "code": 0, + "message": "", + "data":"" +} +``` diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/en/delete_instance_association.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/delete_instance_association.md new file mode 100644 index 000000000..d34c5934d --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/delete_instance_association.md @@ -0,0 +1,39 @@ +### Functional description + +delete association between object's instance. + +### Request Parameters + +{{ common_args_desc }} + +#### General Parameters +| Field | Type | Required | Description | +|----------------------|------------|--------|-----------------------------| +| id | int64 | Yes | the instance association's unique id | + +### Request Parameters Example + +``` json + +``` + +### Return Result Example + +```json +{ + "result": true, + "code": 0, + "message": "", + "data": "success" +} + +``` + +### Return Result Parameters Description + +#### data : + +| Field | Type | Description | +|------------|----------|--------------| + + diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/en/delete_process_module_bind.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/delete_process_module_bind.md new file mode 100644 index 000000000..6ac3d4fbd --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/delete_process_module_bind.md @@ -0,0 +1,38 @@ +### Functional description + +delete process module bind relationship + +### Request Parameters + +{{ common_args_desc }} + +#### Request Parameters Example + +| Field | Type | Required | Description | +|-------|-------------|--------|-------------------------------| +| id | int | No | The unique identifier ID of the deleted data record | +| bk_supplier_account | string | Yes | Supplier account | +| bk_biz_id | int | Yes | Bussiness ID | +| bk_process_id | int | Yes | Process ID | +| bk_module_name | string | yes | ModuleName | + + +### Request Parameters Example + +```python + + +``` + + +### Return Result Example + +```python + +{ + "result": true, + "code": 0, + "message": "", + "data": "success" +} +``` diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/en/find_host_by_module.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/find_host_by_module.md new file mode 100644 index 000000000..64b7e49cb --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/find_host_by_module.md @@ -0,0 +1,153 @@ +### Functional description + +find host by module id + +### Request Parameters + +{{ common_args_desc }} + +#### General Parameters + +| Field | Type | Required | Description | +|----------------------|------------|--------|-----------------------------| +| metadata | object | Yes | request meta data | +| bk_module_ids | int array | Yes | module id array | +| page | object | Yes | page condition | + + +metadata params + +| Field | Type | Required | Description | +|---------------------|------------|--------|-----------------------------| +| label | string map | Yes |the label data request should with, such as biz info | + + +label params + +| Field | Type | Required | Description | +|---------------------|------------|--------|-----------------------------| +| bk_biz_id | string | Yes | bussiness ID | + +### Request Parameters Example + +``` python +{ + "metadata":{ + "label":{ + "bk_biz_id":"3" + } + }, + "bk_module_ids":[ + 56 + ], + "page":{ + "start":0, + "limit":10 + } +} +``` + +### Return Result Example + +```python + +{ + "result":true, + "bk_error_code":0, + "bk_error_msg":"success", + "data":{ + "count":1, + "info":[ + { + "biz":[ + { + "bk_biz_developer":"", + "bk_biz_id":2, + "bk_biz_maintainer":"admin", + "bk_biz_name":"蓝鲸" + } + ], + "host":{ + "bk_asset_id":"DKUXHBUH189", + "bk_bak_operator":"admin", + "bk_cloud_id":[ + { + "id":"0", + "bk_obj_id":"plat", + "bk_obj_icon":"", + "bk_inst_id":0, + "bk_obj_name":"", + "bk_inst_name":"default area" + } + ], + "bk_comment":"", + "bk_cpu":8, + "bk_cpu_mhz":2609, + "bk_cpu_module":"E5-2620", + "bk_disk":300000, + "bk_host_id":17, + "bk_host_innerip":"192.168.1.1", + "bk_host_name":"nginx-1", + "bk_host_outerip":"", + "bk_isp_name":null, + "bk_mac":"", + "bk_mem":32000, + "bk_os_bit":"" + }, + "module":[ + { + "TopModuleName":"蓝鲸##公共组件##consul", + "bk_bak_operator":"", + "bk_biz_id":2, + "bk_module_id":35, + "bk_module_name":"consul", + "bk_module_type":"1", + "bk_parent_id":8, + "bk_set_id":8, + "bk_supplier_account":"0", + "create_time":"2018-05-16T21:03:22.724+08:00", + "default":0, + "last_time":"2018-05-16T21:03:22.724+08:00", + "operator":"" + } + ], + "set":[ + { + "TopSetName":"蓝鲸##公共组件", + "bk_biz_id":2, + "bk_capacity":null, + "bk_parent_id":3, + "bk_service_status":"1", + "bk_set_desc":"111", + "bk_set_env":"3", + "bk_set_id":8, + "bk_set_name":"公共组件", + "bk_supplier_account":"0", + "create_time":"2018-05-16T21:03:22.692+08:00", + "default":0, + "description":"", + "last_time":"2018-05-18T11:50:53.947+08:00" + } + ] + } + ] + } +} +``` + + +### Return Result Parameters Description + +| Field | Type | Description | +|------------|----------|--------------| +| count | int |the count of result| +| info | array |the record info| + +#### data : + +| Field | Type | Description | +|------------|----------|--------------| +| biz| object| host bussiness information | +| set| object | host set information| +| module| object |host module information | +| host| object |host information | diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/en/find_instance_association.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/find_instance_association.md new file mode 100644 index 000000000..88ae559b7 --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/find_instance_association.md @@ -0,0 +1,88 @@ +### Functional description + +find association between object's instance. + +### Request Parameters + +{{ common_args_desc }} + +#### General Parameters + +| Field | Type | Required | Description | +|----------------------|------------|--------|-----------------------------| +| metadata | object | Yes | request meta data | +| condition | string map | Yes | query condition | + + +metadata params + +| Field | Type | Required | Description | +|---------------------|------------|--------|-----------------------------| +| label | string map | Yes |the label data request should with, such as biz info | + + +label params + +| Field | Type | Required | Description | +|---------------------|------------|--------|-----------------------------| +| bk_biz_id | string | Yes | business's ID | + +condition params +| Field | Type | Required | Description | +|---------------------|------------|--------|-----------------------------| +| bk_obj_asst_id | string | Yes | object's association unique id| +| bk_asst_id | string | NO | object's association kind unique name| +| bk_obj_id | string | NO | the association's source object's id| +| bk_asst_id | string | NO | the association's destination object's id| + + +### Request Parameters Example + +``` json +{ + "condition": { + "bk_obj_asst_id": "bk_switch_belong_bk_host", + "bk_asst_id": "", + "bk_object_id": "", + "bk_asst_obj_id": "" + }, + "metadata":{ + "label":{ + "bk_biz_id":"3" + } + } +} +``` + +### Return Result Example + +```json +{ + "result": true, + "code": 0, + "message": "", + "data": [{ + "bk_obj_asst_id": "bk_switch_belong_bk_host", + "bk_obj_id":"switch", + "bk_asst_obj_id":"host", + "bk_inst_id":12, + "bk_asst_inst_id":13 + }] +} + +``` + + +### Return Result Parameters Description + +#### data : + +| Field | Type | Description | +|------------|----------|--------------| +|id|int64|the association's unique id| +| bk_obj_asst_id| string| auto generated id, which represent this association.| +| bk_obj_id| string| the association source object's id | +| bk_asst_obj_id| string| the association destination object's id| +| bk_inst_id| int64| the association source object's instance id| +| bk_asst_inst_id| int64| the association destination object's instance id| + diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/en/find_object_association.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/find_object_association.md new file mode 100644 index 000000000..78b8f1355 --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/find_object_association.md @@ -0,0 +1,98 @@ +### Functional description + +find association between object. + +### Request Parameters + +{{ common_args_desc }} + +#### General Parameters + +| Field | Type | Required | Description | +|----------------------|------------|--------|-----------------------------| +| metadata | object | Yes | request meta data | +| condition | string map | Yes | query condition | + + +metadata params + +| Field | Type | Required | Description | +|---------------------|------------|--------|-----------------------------| +| label | string map | Yes |the label data request should with, such as biz info | + + +label params + +| Field | Type | Required | Description | +|---------------------|------------|--------|-----------------------------| +| bk_biz_id | string | Yes | business's ID | + +condition params +| Field | Type | Required | Description | +|---------------------|------------|--------|-----------------------------| +| bk_asst_id | string | Yes | object's association kind unique name| +| bk_obj_id | string | Yes | the association's source object's id| +| bk_asst_id | string | Yes | the association's destination object's id| + + +### Request Parameters Example + +``` json +{ + "condition": { + "bk_asst_id": "belong", + "bk_obj_id": "bk_switch", + "bk_asst_obj_id": "bk_host" + }, + "metadata":{ + "label":{ + "bk_biz_id":"1" + } + } +} +``` + +### Return Result Example + +```json +{ + "result": true, + "code": 0, + "message": "", + "data": [ + { + "id": 1, + "bk_obj_asst_id": "bk_switch_belong_bk_host", + "bk_obj_asst_name": "", + "bk_asst_id": "belong", + "bk_asst_name": "belong", + "bk_obj_id": "bk_switch", + "bk_obj_name": "switch", + "bk_asst_obj_id": "bk_host", + "bk_asst_obj_name": "host", + "mapping": "1:n", + "on_delete": "none" + } + ] +} + +``` + + +### Return Result Parameters Description + +#### data : + +| Field | Type | Description | +|------------|----------|--------------| +|id|int64|the association's unique id| +| bk_obj_asst_id| string| auto generated id, which represent this association.| +| bk_obj_asst_name| string| the alias name for this association. | +| bk_asst_id| string| association kind id | +| bk_asst_name| string| association kind name | +| bk_obj_id| string| the association source object's id | +| bk_obj_name| string| the association source object's name | +| bk_asst_obj_id| string| the association destination object's id| +| bk_asst_obj_name| string| the association destination object's name| +| mapping| string| association between object's instance type, could be one of [1:1, 1:n, n:n] | +| on_delete| string| the action when this association is delete, could be one of [none, delete_src, delete_dest], "none" means do nothing, "delete_src" means delete source object's instance, "delete_dest" means delete destination object's instance.| diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/en/get_biz_internal_module.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/get_biz_internal_module.md new file mode 100644 index 000000000..c60b1598c --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/get_biz_internal_module.md @@ -0,0 +1,54 @@ +### Functional description + +get business's idle and fault modules. + +### Request Parameters + +{{ common_args_desc }} + +#### Request Parameters Example + +### Request Parameters Example + +``` python + +``` + +### Return Result Example + +```python +{ + "result": true, + "code": 0, + "message": "success", + "data": { + "bk_set_id": 2, + "bk_set_name": "idle pool", + "module": [ + { + "bk_module_id": 3, + "bk_module_name": "idle machine" + }, + { + "bk_module_id": 4, + "bk_module_name": "fault machine" + } + ] + } +} +``` + +### Return Result Parameters Description + +#### data description + +| Field | Type | Description | +|------------|----------|--------------| +|bk_set_id | int64 | the set id that idle and fault machine belongs to | +|bk_set_name | string |the set name that idle and fault machine belongs to | + +#### module description +| Field | Type | Description | +|------------|----------|--------------| +|bk_module_id | int64 | module's id | +|bk_module_name | string |module's name| \ No newline at end of file diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/en/get_mainline_object_topo.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/get_mainline_object_topo.md new file mode 100644 index 000000000..64034cd28 --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/get_mainline_object_topo.md @@ -0,0 +1,77 @@ +### Functional description + +get mainline object's business topology + +### Request Parameters + +{{ common_args_desc }} + +#### Request Parameters Example + +### Request Parameters Example + +``` python + +``` + +### Return Result Example + +```python +{ + "result": true, + "bk_error_code": 0, + "bk_error_msg": "success", + "data": [ + { + "bk_obj_id": "biz", + "bk_obj_name": "business", + "bk_supplier_account": "0", + "bk_next_obj": "set", + "bk_next_name": "set", + "bk_pre_obj_id": "", + "bk_pre_obj_name": "" + }, + { + "bk_obj_id": "set", + "bk_obj_name": "set", + "bk_supplier_account": "0", + "bk_next_obj": "module", + "bk_next_name": "module", + "bk_pre_obj_id": "biz", + "bk_pre_obj_name": "business" + }, + { + "bk_obj_id": "module", + "bk_obj_name": "module", + "bk_supplier_account": "0", + "bk_next_obj": "host", + "bk_next_name": "host", + "bk_pre_obj_id": "set", + "bk_pre_obj_name": "set" + }, + { + "bk_obj_id": "host", + "bk_obj_name": "host", + "bk_supplier_account": "0", + "bk_next_obj": "", + "bk_next_name": "", + "bk_pre_obj_id": "module", + "bk_pre_obj_name": "module" + } + ] +} +``` + +### Return Result Parameters Description + +#### data + +| Field | Type | Description | +|------------|----------|--------------| +|bk_obj_id | string | object's unique id | +|bk_obj_name | string | object's name | +|bk_supplier_account | string | supplier's account | +|bk_next_obj | string | the next object's unique id | +|bk_next_name | string | the next object's name | +|bk_pre_obj_id | string | the previous object's unique id | +|bk_pre_obj_name | string | the previous object's name | \ No newline at end of file diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/en/get_operation_log.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/get_operation_log.md index 308ca1f0e..a01db70b5 100644 --- a/paas-ce/paas/esb/components/confapis/cc/apidocs/en/get_operation_log.md +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/get_operation_log.md @@ -89,11 +89,11 @@ get operation log "header":[ { "bk_property_id":"bk_host_innerip", - "bk_property_name":"内网IP" + "bk_property_name":"InnerIP" }, { "bk_property_id":"bk_host_outerip", - "bk_property_name":"外网IP" + "bk_property_name":"OutterIP" } ], "type":"map" diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/en/get_process_bind_module.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/get_process_bind_module.md new file mode 100644 index 000000000..2193a2c93 --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/get_process_bind_module.md @@ -0,0 +1,65 @@ +### Functional description + +get process bind module + +### Request Parameters + +{{ common_args_desc }} + +#### Request Parameters Example + +| Field | Type | Required | Description | +|----------------------|------------|--------|-----------------------| +| bk_supplier_account | string |Yes | Supplier account | +| bk_biz_id | int | Yes | Bussiness ID | +| bk_process_id | int | Yes | Process ID | + + +### Request Parameters Example + +```python + + +``` + +### Return Result Example + +```python + +{ + "result":true, + "bk_error_code":0, + "bk_error_msg":"", + "data":[ + { + "bk_module_name":"db", + "set_num":10, + "is_bind":0 + }, + { + "bk_module_name":"gs", + "set_num":5, + "is_bind":1 + } + ] +} +``` + +### Return Result Parameters Description + +| Field | Type | Description | +|------------|----------|--------------| +| result | bool |request result true or false| +| bk_error_code | int |error code. 0 represent success, >0 represent failure code | +| bk_error_msg | string |error message from failed request| +| data | object |the data response| + +#### data : + +| Field | Type | Description | +|------------|----------|--------------| +| bk_module_name| string| Module Name | +| set_num| int | set number | +| is_bind| int | is bind with | + + diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/en/search_object_topo.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/search_object_topo.md index ff1cbd605..b837983bf 100644 --- a/paas-ce/paas/esb/components/confapis/cc/apidocs/en/search_object_topo.md +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/en/search_object_topo.md @@ -45,7 +45,7 @@ search object topology "to": { "bk_classification_id": "bk_host_manage", "bk_obj_id": "plat", - "bk_obj_name": "云区域", + "bk_obj_name": "cloud area", "position": "{\"bk_host_manage\":{\"x\":-172,\"y\":-160}}", "bk_supplier_account": "0" } diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/add_instance_association.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/add_instance_association.md new file mode 100644 index 000000000..c348c3b90 --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/add_instance_association.md @@ -0,0 +1,76 @@ +### 功能描述 + +新增模型实例之间的关联关系. + +### 请求参数 + +{{ common_args_desc }} + +#### 接口参数 + +| 字段 | 类型 | 是否必填 | 描述 | +|----------------------|------------|--------|-----------------------------| +| metadata | object | Yes | meta data | +| condition | string map | Yes | 查询条件 | + + +metadata params + +| 字段 | 类型 | 是否必填 | 描述 | +|---------------------|------------|--------|-----------------------------| +| label | string map | Yes |标签信息 | + + +label params + +| 字段 | 类型 | 是否必填 | 描述 | +|---------------------|------------|--------|-----------------------------| +| bk_biz_id | string | Yes | 业务id | + + +condition params + +| 字段 | 类型 | 是否必填 | 描述 | +|---------------------|------------|--------|-----------------------------| +| bk_obj_asst_id | string | Yes | 模型之间关系关系的唯一id| +| bk_inst_id | int64 | Yes | 源模型实例id| +| bk_asst_inst_id | int64 | Yes | 目标模型实例id| + + +### 请求参数示例 + +``` json +{ + "bk_obj_asst_id": "bk_switch_belong_bk_host", + "bk_inst_id": 11, + "bk_asst_inst_id": 21, + "metadata":{ + "label":{ + "bk_biz_id":"1" + } + } +} +``` + +### 返回结果示例 + +```json +{ + "result": true, + "code": 0, + "message": "", + "data": { + "id": 1038 + } +} + +``` + +### 返回结果参数说明 + +#### data + +| 字段 | 类型 | 描述 | +|------------|----------|--------------| +|id|int64|新增的实例关联关系身份id| + diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/bind_process_module.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/bind_process_module.md new file mode 100644 index 000000000..4e23bd6a8 --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/bind_process_module.md @@ -0,0 +1,37 @@ +### 功能描述 + +绑定进程到模块 +### 请求参数 + +{{ common_args_desc }} + +#### 接口参数 + +| 字段 | 类型 | 必选 | 描述 | +|------------|----------|--------|---------------| +| bk_supplier_account | string | 是 | 开发商ID | +| bk_biz_id | int | 是 | 业务ID | +| bk_process_id | int | 是 | 进程ID | +| bk_module_name | string | 是 | 模块名 | + + + + +### 请求参数示例 + +```python + +``` + + +### 返回结果示例 + +```python + +{ + "result":true, + "bk_error_code":0, + "bk_error_msg":"", + "data":"success" +} +``` diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/delete_instance_association.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/delete_instance_association.md new file mode 100644 index 000000000..c03978c97 --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/delete_instance_association.md @@ -0,0 +1,39 @@ +### 功能描述 + +删除模型实例之间的关联关系。 + +### 请求参数 + +{{ common_args_desc }} + +#### 接口参数 +| 字段 | 类型 | 必填 | 描述 | +|----------------------|------------|--------|-----------------------------| +| id | int64 | Yes | 模型实例关联关系的唯一身份id | + +### 请求参数示例 + +``` json + +``` + +### 返回结果示例 + +```json +{ + "result": true, + "code": 0, + "message": "", + "data": "success" +} + +``` + +### 返回结果参数说明 + +#### data + +| 字段 | 类型 | 描述 | +|------------|----------|--------------| + + diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/delete_object_attribute.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/delete_object_attribute.md index 73a96dc88..a6222dc78 100644 --- a/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/delete_object_attribute.md +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/delete_object_attribute.md @@ -22,6 +22,7 @@ "id" : 0 } } +``` ### 返回结果示例 diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/delete_process_module_bind.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/delete_process_module_bind.md new file mode 100644 index 000000000..1f12051b0 --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/delete_process_module_bind.md @@ -0,0 +1,36 @@ +### 功能描述 + +解绑进程模块 + +### 请求参数 + +{{ common_args_desc }} + +#### 接口参数 + +| 字段 | 类型 | 必选 | 描述 | +|-------|-------------|--------|-----------------------| +| bk_supplier_account | string | 是 | 开发商ID | +| bk_biz_id | int | 是 | 业务ID | +| bk_process_id | int | 是 | 进程ID | +| bk_module_name | string | 是 | 模块名 | + + +### 请求参数示例 + +```python + +``` + + +### 返回结果示例 + +```python + +{ + "result": true, + "code": 0, + "message": "", + "data": "success" +} +``` diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/find_host_by_module.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/find_host_by_module.md new file mode 100644 index 000000000..810c247c5 --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/find_host_by_module.md @@ -0,0 +1,160 @@ +### 功能描述 + +根据模块ID查询主机 + +### 请求参数 + +{{ common_args_desc }} + +#### 接口参数 + +| 字段 | 类型 | 必选 | 描述 | +|---------------------|------------|--------|-----------------------------| +| metadata | object | 是 | 请求元数据 | +| bk_module_ids | int array | 是 | 模块ID数组 | +| page | object | 是 | 分页参数 | + +metadata参数 + +| 字段 | 类型 | 必选 | 描述 | +|---------------------|------------|--------|-----------------------------| +| label | string map | 是 | 请求中需要携带的信息,例如业务ID | + +label参数 + +| 字段 | 类型 | 必选 | 描述 | +|---------------------|------------|--------|-----------------------------| +| bk_biz_id | string | 是 | 业务ID | + + +### 请求参数示例 + +```python +{ + "metadata":{ + "label":{ + "bk_biz_id":"3" + } + }, + "bk_module_ids":[ + 56 + ], + "page":{ + "start":0, + "limit":10 + } +} +``` + +### 返回结果示例 + +```python +{ + "result":true, + "bk_error_code":0, + "bk_error_msg":"success", + "data":{ + "count":1, + "info":[ + { + "biz":[ + { + "bk_biz_developer":"", + "bk_biz_id":2, + "bk_biz_maintainer":"admin", + "bk_biz_name":"蓝鲸" + } + ], + "host":{ + "bk_asset_id":"DKUXHBUH189", + "bk_bak_operator":"admin", + "bk_cloud_id":[ + { + "id":"0", + "bk_obj_id":"plat", + "bk_obj_icon":"", + "bk_inst_id":0, + "bk_obj_name":"", + "bk_inst_name":"default area" + } + ], + "bk_comment":"", + "bk_cpu":8, + "bk_cpu_mhz":2609, + "bk_cpu_module":"E5-2620", + "bk_disk":300000, + "bk_host_id":17, + "bk_host_innerip":"192.168.1.1", + "bk_host_name":"nginx-1", + "bk_host_outerip":"", + "bk_isp_name":null, + "bk_mac":"", + "bk_mem":32000, + "bk_os_bit":"" + }, + "module":[ + { + "TopModuleName":"蓝鲸##公共组件##consul", + "bk_bak_operator":"", + "bk_biz_id":2, + "bk_module_id":35, + "bk_module_name":"consul", + "bk_module_type":"1", + "bk_parent_id":8, + "bk_set_id":8, + "bk_supplier_account":"0", + "create_time":"2018-05-16T21:03:22.724+08:00", + "default":0, + "last_time":"2018-05-16T21:03:22.724+08:00", + "operator":"" + } + ], + "set":[ + { + "TopSetName":"蓝鲸##公共组件", + "bk_biz_id":2, + "bk_capacity":null, + "bk_parent_id":3, + "bk_service_status":"1", + "bk_set_desc":"111", + "bk_set_env":"3", + "bk_set_id":8, + "bk_set_name":"公共组件", + "bk_supplier_account":"0", + "create_time":"2018-05-16T21:03:22.692+08:00", + "default":0, + "description":"", + "last_time":"2018-05-18T11:50:53.947+08:00" + } + ] + } + ] + } +} +``` + +### 返回结果参数说明 + +| 名称 | 类型 | 说明 | +|---|---|---|---| +| result | bool | 请求成功与否。true:请求成功;false请求失败 | +| bk_error_code | int | 错误编码。 0表示success,>0表示失败错误 | +| bk_error_msg | string | 请求失败返回的错误信息 | +| data | object| 请求返回的数据 | + +data 字段说明: + +| 名称 | 类型 | 说明 | +|---|---|---|---| +| count| int| 记录条数 | +| info| object array | 主机实际数据 | + + +info 字段说明: + +| 名称 | 类型 | 说明 | +|---|---|---|---| +| biz | object array| 主机所属的业务信息 | +| set| object array | 主机所属的集群信息 | +| module| object array| 主机所属的模块信息 | +| host| object | 主机自身属性| diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/find_instance_association.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/find_instance_association.md new file mode 100644 index 000000000..7a709b93e --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/find_instance_association.md @@ -0,0 +1,90 @@ +### 功能描述 + +查询模型的实例关联关系。 + +### 请求参数 + +{{ common_args_desc }} + +#### 接口参数 + +| 字段 | 类型 | 是否必填 | 描述 | +|----------------------|------------|--------|-----------------------------| +| metadata | object | Yes | meta data | +| condition | string map | Yes | 查询条件 | + + +metadata params + +| 字段 | 类型 | 是否必填 | 描述 | +|---------------------|------------|--------|-----------------------------| +| label | string map | Yes | 标签信息 | + + +label params + +| 字段 | 类型 | 是否必填 | 描述 | +|---------------------|------------|--------|-----------------------------| +| bk_biz_id | string | Yes | 业务ID | + + +condition params + +| 字段 | 类型 | 是否必填 | 描述 | +|---------------------|------------|--------|-----------------------------| +| bk_obj_asst_id | string | Yes | 模型关联关系的唯一id| +| bk_asst_id | string | NO | 关联类型的唯一id| +| bk_obj_id | string | NO | 源模型id| +| bk_asst_id | string | NO | 目标模型id| + + +### 请求参数示例 + +``` json +{ + "condition": { + "bk_obj_asst_id": "bk_switch_belong_bk_host", + "bk_asst_id": "", + "bk_object_id": "", + "bk_asst_obj_id": "" + }, + "metadata":{ + "label":{ + "bk_biz_id":"3" + } + } +} +``` + +### 返回结果示例 + +```json +{ + "result": true, + "code": 0, + "message": "", + "data": [{ + "bk_obj_asst_id": "bk_switch_belong_bk_host", + "bk_obj_id":"switch", + "bk_asst_obj_id":"host", + "bk_inst_id":12, + "bk_asst_inst_id":13 + }] +} + +``` + + +### 返回结果参数说明 + +#### data + +| 字段 | 类型 | 描述 | +|------------|----------|--------------| +|id|int64|the association's unique id| +| bk_obj_asst_id| string| 自动生成的模型关联关系id.| +| bk_obj_id| string| 关联关系源模型id | +| bk_asst_obj_id| string| 关联关系目标模型id| +| bk_inst_id| int64| 源模型实例id| +| bk_asst_inst_id| int64| 目标模型实例id| + diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/find_object_association.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/find_object_association.md new file mode 100644 index 000000000..08b53c57d --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/find_object_association.md @@ -0,0 +1,100 @@ +### 功能描述 + +查询模型的实例之间的关联关系。 + +### 请求参数 + +{{ common_args_desc }} + +#### 接口参数 + +| 字段 | 类型 | 是否必填 | 描述 | +|----------------------|------------|--------|-----------------------------| +| metadata | object | Yes | meta data | +| condition | string map | Yes | 查询条件 | + + +metadata params + +| 字段 | 类型 | 是否必填 | 描述 | +|---------------------|------------|--------|-----------------------------| +| label | string map | Yes |标签信息 | + + +label params + +| 字段 | 类型 | 是否必填 | 描述 | +|---------------------|------------|--------|-----------------------------| +| bk_biz_id | string | Yes | 业务id | + + +condition params + +| 字段 | 类型 | 是否必填 | 描述 | +|---------------------|------------|--------|-----------------------------| +| bk_asst_id | string | Yes | 模型的关联类型唯一id| +| bk_obj_id | string | Yes | 源模型id| +| bk_asst_id | string | Yes | 目标模型id| + + +### 请求参数示例 + +``` json +{ + "condition": { + "bk_asst_id": "belong", + "bk_obj_id": "bk_switch", + "bk_asst_obj_id": "bk_host" + }, + "metadata":{ + "label":{ + "bk_biz_id":"1" + } + } +} +``` + +### 返回结果示例 + +```json +{ + "result": true, + "code": 0, + "message": "", + "data": [ + { + "id": 1, + "bk_obj_asst_id": "bk_switch_belong_bk_host", + "bk_obj_asst_name": "", + "bk_asst_id": "belong", + "bk_asst_name": "belong", + "bk_obj_id": "bk_switch", + "bk_obj_name": "switch", + "bk_asst_obj_id": "bk_host", + "bk_asst_obj_name": "host", + "mapping": "1:n", + "on_delete": "none" + } + ] +} + +``` + + +### 返回结果参数说明 + +#### data + +| 字段 | 类型 | 描述 | +|------------|----------|--------------| +| id|int64|模型关联关系的身份id| +| bk_obj_asst_id| string| 模型关联关系的唯一id.| +| bk_obj_asst_name| string| 关联关系的别名. | +| bk_asst_id| string| 关联类型id| +| bk_asst_name| string| 关联类型名称 | +| bk_obj_id| string| 源模型id | +| bk_obj_name| string| 源模型名称 | +| bk_asst_obj_id| string| 目标模型id| +| bk_asst_obj_name| string| 目标模型名称| +| mapping| string| 源模型与目标模型关联关系实例的映身关系,可以是以下中的一种[1:1, 1:n, n:n] | +| on_delete| string| 删除关联关系时的动作, 取值为以下其中的一种 [none, delete_src, delete_dest], "none" 什么也不做, "delete_src" 删除源模型的实例, "delete_dest" 删除目标模型的实例.| diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/get_biz_internal_module.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/get_biz_internal_module.md new file mode 100644 index 000000000..ddbd9d9cd --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/get_biz_internal_module.md @@ -0,0 +1,64 @@ +### 功能描述 + +获取业务空闲机和故障机模块 + +### 请求参数 + +{{ common_args_desc }} + + +#### 接口参数 + +| 字段 | 类型 | 必选 | 描述 | +|-----------|------------|--------|------------| +| bk_biz_id | int | 是 | 业务ID | +| bk_supplier_account | string | 是 | 开发商账号 | + +### 请求参数示例 + +```python + +{ + "bk_biz_id":0, + "bk_supplier_account":"0" +} +``` + +### 返回结果示例 + +```python +{ + "result": true, + "code": 0, + "message": "success", + "data": { + "bk_set_id": 2, + "bk_set_name": "空闲机池", + "module": [ + { + "bk_module_id": 3, + "bk_module_name": "空闲机" + }, + { + "bk_module_id": 4, + "bk_module_name": "故障机" + } + ] + } +} +``` + +### 返回结果参数说明 + +#### data说明 +| 字段 | 类型 | 描述 | +|-----------|------------|------------| +|bk_set_id | int64 | 空闲机和故障机所属的set的实例ID | +|bk_set_name | string |空闲机和故障机所属的set的实例名称| + +#### module说明 +| 字段 | 类型 | 描述 | +|-----------|------------|------------| +|bk_module_id | int64 | 空闲机或故障机的的实例ID | +|bk_module_name | string |空闲机或故障机的实例名称| + diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/get_mainline_object_topo.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/get_mainline_object_topo.md new file mode 100644 index 000000000..fe7924060 --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/get_mainline_object_topo.md @@ -0,0 +1,76 @@ +### 功能描述 + +获取主线模型的业务拓扑 + +### 请求参数 + +无 + +#### 接口参数 + + +### 请求参数示例 + +```python +``` + +### 返回结果示例 + +```python +{ + "result": true, + "bk_error_code": 0, + "bk_error_msg": "success", + "data": [ + { + "bk_obj_id": "biz", + "bk_obj_name": "业务", + "bk_supplier_account": "0", + "bk_next_obj": "set", + "bk_next_name": "集群", + "bk_pre_obj_id": "", + "bk_pre_obj_name": "" + }, + { + "bk_obj_id": "set", + "bk_obj_name": "集群", + "bk_supplier_account": "0", + "bk_next_obj": "module", + "bk_next_name": "模块", + "bk_pre_obj_id": "biz", + "bk_pre_obj_name": "业务" + }, + { + "bk_obj_id": "module", + "bk_obj_name": "模块", + "bk_supplier_account": "0", + "bk_next_obj": "host", + "bk_next_name": "主机", + "bk_pre_obj_id": "set", + "bk_pre_obj_name": "集群" + }, + { + "bk_obj_id": "host", + "bk_obj_name": "主机", + "bk_supplier_account": "0", + "bk_next_obj": "", + "bk_next_name": "", + "bk_pre_obj_id": "module", + "bk_pre_obj_name": "模块" + } + ] +} +``` + +### 返回结果参数说明 + +#### data +| 字段 | 类型 | 描述 | +|-----------|------------|------------| +|bk_obj_id | string | 模型的唯一ID | +|bk_obj_name | string |模型名称| +|bk_supplier_account | string |开发商帐户名称| +|bk_next_obj | string |当前模型的下一个模型唯一ID| +|bk_next_name | string |当前模型的下一个模型名称| +|bk_pre_obj_id | string |当前模型的前一个模型的唯一ID| +|bk_pre_obj_name | string |当前模型的前一个模型的名称| diff --git a/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/get_process_bind_module.md b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/get_process_bind_module.md new file mode 100644 index 000000000..fc103915f --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/cc/apidocs/zh_hans/get_process_bind_module.md @@ -0,0 +1,67 @@ +### 功能描述 + +获取进程绑定模块 + +### 请求参数 + +{{ common_args_desc }} + +#### 接口参数 + +| 字段 | 类型 | 必选 | 描述 | +|----------------------|------------|--------|-----------------------| +| bk_supplier_account | string |是 | 开发商ID | +| bk_biz_id | int | 是 | 业务ID | +| bk_process_id | int | 是 | 进程ID | + + +### 请求参数示例 + +```python + + +``` + +### 返回结果示例 + +```python + +{ + "result":true, + "bk_error_code":0, + "bk_error_msg":"", + "data":[ + { + "bk_module_name":"db", + "set_num":10, + "is_bind":0 + }, + { + "bk_module_name":"gs", + "set_num":5, + "is_bind":1 + } + ] +} +``` + +### 返回结果参数说明 + +#### data + +| 名称 | 类型 | 描述 | +|---|---|---| +| result | bool | 请求成功与否。true:请求成功;false请求失败 | +| bk_error_code | int | 错误编码。 0表示success,>0表示失败错误 | +| bk_error_msg | string | 请求失败返回的错误信息 | +| data | object | 请求返回的数据 | + +#### data 字段说明: + +| 名称 | 类型 | 描述 | +|---|---|---|---| +| bk_module_name| string| 模块名 | +| set_num| int | 所属集群个数 | +| is_bind| int | 是否绑定 | + + diff --git a/paas-ce/paas/esb/components/confapis/cc/cc.yaml b/paas-ce/paas/esb/components/confapis/cc/cc.yaml index c3d6077db..1e82cbccf 100644 --- a/paas-ce/paas/esb/components/confapis/cc/cc.yaml +++ b/paas-ce/paas/esb/components/confapis/cc/cc.yaml @@ -9,7 +9,16 @@ comp_codename: generic.v2.cc.cc_component dest_path: /api/v3/biz/status/{flag}/{bk_supplier_account}/{bk_biz_id} dest_http_method: PUT - + +- path: /v2/cc/batch_delete_set/ + name: batch_delete_set + label: 批量删除集群 + label_en: delete set batch + suggest_method: POST + api_type: operate + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/set/{bk_biz_id}/batch + dest_http_method: DELETE - path: /v2/cc/create_inst/ name: create_inst @@ -40,7 +49,16 @@ comp_codename: generic.v2.cc.cc_component dest_path: /api/v3/inst/{bk_supplier_account}/{bk_obj_id}/{bk_inst_id} dest_http_method: PUT - + +- path: /v2/cc/batch_update_inst/ + name: batch_update_inst + label: 批量更新对象实例 + label_en: update inst batch + suggest_method: POST + api_type: operate + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/inst/{bk_supplier_account}/{bk_obj_id}/batch + dest_http_method: PUT - path: /v2/cc/delete_inst/ name: delete_inst @@ -52,6 +70,15 @@ dest_path: /api/v3/inst/{bk_supplier_account}/{bk_obj_id}/{bk_inst_id} dest_http_method: DELETE +- path: /v2/cc/batch_delete_inst/ + name: batch_delete_inst + label: 批量删除实例 + label_en: delete inst batch + suggest_method: POST + api_type: operate + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/inst/{bk_supplier_account}/{bk_obj_id}/batch + dest_http_method: DELETE - path: /v2/cc/search_inst_association_topo/ name: search_inst_association_topo @@ -333,7 +360,27 @@ comp_codename: generic.v2.cc.cc_component dest_path: /api/v3/event/subscribe/telnet dest_http_method: POST - + +- path: /v2/cc/transfer_sethost_to_idle_module/ + name: transfer_sethost_to_idle_module + label: 清空业务下集群/模块中主机 + label_en: transfer host in set or module to idle module + suggest_method: POST + api_type: operate + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/hosts/modules/idle/set + dest_http_method: POST + +- path: /v2/cc/clone_host_property/ + name: clone_host_property + label: 克隆主机属性 + label_en: clone host property + suggest_method: POST + api_type: operate + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/hosts/property/clone + dest_http_method: PUT + - path: /v2/cc/get_operation_log/ name: get_operation_log label: 获取操作日志 @@ -343,5 +390,136 @@ comp_codename: generic.v2.cc.cc_component dest_path: /api/v3/audit/search dest_http_method: POST - +- path: /v2/cc/add_host_lock/ + name: add_host_lock + label: 新加主机锁 + label_en: add host lock + suggest_method: POST + api_type: operate + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/host/lock + dest_http_method: POST + +- path: /v2/cc/delete_host_lock/ + name: delete_host_lock + label: 删除主机锁 + label_en: delete host lock + suggest_method: POST + api_type: operate + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/host/lock + dest_http_method: DELETE + + +- path: /v2/cc/search_host_lock/ + name: search_host_lock + label: 查询主机锁 + label_en: search host lock + suggest_method: POST + api_type: query + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/host/lock/search + dest_http_method: POST + +- path: /v2/cc/get_mainline_object_topo/ + name: get_mainline_object_topo + label: 查询主线模型的业务拓扑 + label_en: get mainline object's business topology + suggest_method: GET + api_type: query + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/topo/model/{bk_supplier_account} + dest_http_method: GET + +- path: /v2/cc/get_biz_internal_module/ + name: get_biz_internal_module + label: 查询业务的空闲机和故障机模块 + label_en: get business's fault and idle modules + suggest_method: GET + api_type: query + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/topo/internal/{bk_supplier_account}/{bk_biz_id} + dest_http_method: GET + +- path: /v2/cc/get_process_bind_module/ + name: get_process_bind_module + label: 查询进程绑定模块 + label_en: get module bind with process + suggest_method: GET + api_type: query + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/proc/module/{bk_supplier_account}/{bk_biz_id}/{bk_process_id} + dest_http_method: GET + +- path: /v2/cc/bind_process_module/ + name: bind_process_module + label: 绑定进程到模块 + label_en: bind process to module + suggest_method: POST + api_type: operate + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/proc/module/{bk_supplier_account}/{bk_biz_id}/{bk_process_id}/{bk_module_name} + dest_http_method: PUT + +- path: /v2/cc/delete_process_module_bind/ + name: delete_process_module_bind + label: 解绑进程模块 + label_en: delete process module bind relationship + suggest_method: POST + api_type: operate + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/proc/module/{bk_supplier_account}/{bk_biz_id}/{bk_process_id}/{bk_module_name} + dest_http_method: DELETE + +- path: /v2/cc/find_host_by_module/ + name: find_host_by_module + label: 根据模块查询主机 + label_en: find host by module + suggest_method: POST + api_type: query + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/findmany/modulehost + dest_http_method: POST + +- path: /v2/cc/find_object_association/ + name: find_object_association + label: 查询模型之间的关联关系 + label_en: find object's association + suggest_method: POST + api_type: query + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/find/objectassociation + dest_http_method: POST + +- path: /v2/cc/find_instance_association/ + name: find_instance_association + label: 查询模型实例之间的关联关系 + label_en: find association between object's instance + suggest_method: POST + api_type: query + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/find/instassociation + dest_http_method: POST + +- path: /v2/cc/add_instance_association/ + name: add_instance_association + label: 新建模型实例之间的关联关系 + label_en: add association between object's instance + suggest_method: POST + api_type: query + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/create/instassociation + dest_http_method: POST + +- path: /v2/cc/delete_instance_association/ + name: delete_instance_association + label: 删除模型实例之间的关联关系 + label_en: delete association between object's instance + method: DELETE + api_type: query + comp_codename: generic.v2.cc.cc_component + dest_path: /api/v3/delete/instassociation/{id} + dest_http_method: DELETE + + diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/create_periodic_task.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/create_periodic_task.md index ce7bca4cc..90d8aa233 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/create_periodic_task.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/create_periodic_task.md @@ -13,7 +13,7 @@ Create a periodic task | template_id | string | YES | ID of template which used to create task | | bk_biz_id | string | YES | business ID | | name | string | YES | name of task | -| cron | object | YES | crontab object | +| cron | dict | YES | crontab dict | | flow_type | string | NO | flow type,common: common flow,common_func:functional flow | | constants | dict | NO | global variables,details are described below | @@ -37,7 +37,7 @@ constant value ### Request Parameters Example -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -53,7 +53,7 @@ constant value ### Return Result Example -```python +``` { "message": "", "data": { @@ -248,7 +248,7 @@ constant value } ``` -### Return Result Parameters DescriptionExample +### Return Result Description | Field | Type | Description | |-----------|----------|-----------| @@ -268,11 +268,11 @@ constant value | enabled | bool | is the task enabled | | id | int | task id | | template_id | string | template id for the task | -| form | object | form object for the task | -| pipeline_tree | object | flow tree for the task | +| form | dict | form dict for the task | +| pipeline_tree | dict | flow tree for the task | -#### data.pipeline_tree DescriptionExample +#### data.pipeline_tree | Field | Type | Description | |-----------|----------|-----------| @@ -299,4 +299,4 @@ KEY, the format is like ${key} | source_type | string | source of variable, custom mean manual variable, component_inputs means variables comes from task node inputs parameters, component_outputs means variables comes from task node outputs parameters | | custom_type | string | custom type, which is not empty when source_type is custom, the value is input ,or textarea, or datetime, or int | | source_tag | string | source tag and atom info, which is not empty when source_type is component_inputs or component_outputs | -| source_info | dict | source info about task node ID | \ No newline at end of file +| source_info | dict | source info about task node ID | diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/create_task.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/create_task.md index c4d952b70..e0fed07c4 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/create_task.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/create_task.md @@ -12,9 +12,11 @@ Create a task with a flow template |---------------|------------|--------|------------------| | bk_biz_id | string | YES | the business ID | | template_id | string | YES | the flow template ID | +| template_source | string | NO | source of flow,default value is business. business: from business, common: from common flow | | name | string | YES | Task name | | flow_type | string | NO | flow type,common: common flow,common_func:functional flow | | constants | dict | NO | global variables,details are described below | +| exclude_task_nodes_id | list | NO | nodes id not be executed, which are set ignore in flow | #### constants.KEY @@ -26,7 +28,7 @@ constant value, the type of value should be same with data from API[get_template ### Request Parameters Example -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -43,16 +45,163 @@ constant value, the type of value should be same with data from API[get_template ### Return Result Example -```python +``` { "result": true, "data": { - "task_id": 10 + "task_id": 10, + "task_url": "http://bk_sops_host/taskflow/execute/3/?instance_id=15364", + "pipeline_tree": { + "activities": { + "node9b5ae13799d63e179f0ce3088b62": { + "outgoing": "line27bc7b4ccbcf37ddb9d1f6572a04", + "incoming": "line490caa49d2a03e64829693281032", + "name": "timing", + "error_ignorable": false, + "component": { + "code": "sleep_timer", + "data": { + "bk_timing": { + "hook": false, + "value": "2" + } + } + }, + "stage_name": "步骤1", + "can_retry": true, + "isSkipped": true, + "type": "ServiceActivity", + "optional": false, + "id": "node9b5ae13799d63e179f0ce3088b62", + "loop": null + }, + "node880ded556c6c3c269be3cedc64b6": { + "outgoing": "line490caa49d2a03e64829693281032", + "incoming": "lineb83161d6e0593ad68d9ec73a961b", + "name": "暂停", + "error_ignorable": false, + "component": { + "code": "pause_node", + "data": {} + }, + "stage_name": "步骤1", + "can_retry": true, + "isSkipped": true, + "type": "ServiceActivity", + "optional": true, + "id": "node880ded556c6c3c269be3cedc64b6", + "loop": null + } + }, + "end_event": { + "type": "EmptyEndEvent", + "outgoing": "", + "incoming": "line27bc7b4ccbcf37ddb9d1f6572a04", + "id": "node5c48f37aa9f0351e8b43ab6a2295", + "name": "" + }, + "outputs": [], + "flows": { + "line490caa49d2a03e64829693281032": { + "is_default": false, + "source": "node880ded556c6c3c269be3cedc64b6", + "id": "line490caa49d2a03e64829693281032", + "target": "node9b5ae13799d63e179f0ce3088b62" + }, + "lineb83161d6e0593ad68d9ec73a961b": { + "is_default": false, + "source": "noded383bc1d7387391f889c6bab18b8", + "id": "lineb83161d6e0593ad68d9ec73a961b", + "target": "node880ded556c6c3c269be3cedc64b6" + }, + "line27bc7b4ccbcf37ddb9d1f6572a04": { + "is_default": false, + "source": "node9b5ae13799d63e179f0ce3088b62", + "id": "line27bc7b4ccbcf37ddb9d1f6572a04", + "target": "node5c48f37aa9f0351e8b43ab6a2295" + } + }, + "gateways": {}, + "line": [ + { + "source": { + "id": "node9b5ae13799d63e179f0ce3088b62", + "arrow": "Right" + }, + "target": { + "id": "node5c48f37aa9f0351e8b43ab6a2295", + "arrow": "Left" + }, + "id": "line27bc7b4ccbcf37ddb9d1f6572a04" + }, + { + "source": { + "id": "node880ded556c6c3c269be3cedc64b6", + "arrow": "Right" + }, + "target": { + "id": "node9b5ae13799d63e179f0ce3088b62", + "arrow": "Left" + }, + "id": "line490caa49d2a03e64829693281032" + }, + { + "source": { + "id": "noded383bc1d7387391f889c6bab18b8", + "arrow": "Right" + }, + "id": "lineb83161d6e0593ad68d9ec73a961b", + "target": { + "id": "node880ded556c6c3c269be3cedc64b6", + "arrow": "Left" + } + } + ], + "start_event": { + "type": "EmptyStartEvent", + "outgoing": "lineb83161d6e0593ad68d9ec73a961b", + "incoming": "", + "id": "noded383bc1d7387391f889c6bab18b8", + "name": "" + }, + "id": "node7ef6970d06ad3bc092594cb5ec5f", + "constants": {}, + "location": [ + { + "stage_name": "步骤1", + "name": "暂停", + "y": 135, + "x": 300, + "type": "tasknode", + "id": "node880ded556c6c3c269be3cedc64b6" + }, + { + "y": 150, + "x": 1000, + "type": "endpoint", + "id": "node5c48f37aa9f0351e8b43ab6a2295" + }, + { + "stage_name": "步骤1", + "name": "timing", + "y": 135, + "x": 595, + "type": "tasknode", + "id": "node9b5ae13799d63e179f0ce3088b62" + }, + { + "y": 150, + "x": 80, + "type": "startpoint", + "id": "noded383bc1d7387391f889c6bab18b8" + } + ] + } } } ``` -### Return Result Parameters DescriptionExample +### Return Result Description | Field | Type | Description | |-----------|----------|-----------| @@ -60,8 +209,39 @@ constant value, the type of value should be same with data from API[get_template | data | dict | data returned when result is true, details are described below | | message | string | error message returned when result is false | -#### data 说明 +#### data | Field | Type | Description | |-----------|----------|-----------| | task_id | int | the task instance ID | +| task_url | str | task instance url | +| pipeline_tree | dict | task pipeline tree | + +#### data.pipeline_tree + +| Field | Type | Description | +|-----------|----------|-----------| +| start_event | dict | start node | +| end_event | dict | end node | +| activities | dict | task node(atoms or subprocess)info | +| gateways | dict | gateways(parallel gateway、exclusive gateway、exclusive gateway)info | +| flows | dict | sequenceFlow(the line between nodes)info | +| constants | dict | global variables, details are described below | +| outputs | list | outputs info, indicate outputs field of global | + +#### data.pipeline_tree.constants.KEY + +KEY, the format is like ${key} + +#### data.pipeline_tree.constants.VALUE + +| Field | Type | Description | +|-----------|----------|-----------| +| key | string | same with KEY | +| name | string | name | +| index | int | display order at the front end | +| desc | string | description | +| source_type | string | source of variable, custom mean manual variable, component_inputs means variables comes from task node inputs parameters, component_outputs means variables comes from task node outputs parameters | +| custom_type | string | custom type, which is not empty when source_type is custom, the value is input ,or textarea, or datetime, or int | +| source_tag | string | source tag and atom info, which is not empty when source_type is component_inputs or component_outputs | +| source_info | dict | source info about task node ID | diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_periodic_task_info.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_periodic_task_info.md index cda88592f..66f27263a 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_periodic_task_info.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_periodic_task_info.md @@ -16,7 +16,7 @@ Query periodic task detail ### Request Parameters Example -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -28,7 +28,7 @@ Query periodic task detail ### Return Result Example -```python +``` { "message": "", "data": { @@ -223,7 +223,7 @@ Query periodic task detail } ``` -### Return Result Parameters DescriptionExample +### Return Result Description | Field | Type | Description | |-----------|----------|-----------| @@ -243,11 +243,11 @@ Query periodic task detail | enabled | bool | is the task enabled | | id | int | task id | | template_id | string | template id for the task | -| form | object | form object for the task | -| pipeline_tree | object | flow tree for the task | +| form | dict | form dict for the task | +| pipeline_tree | dict | flow tree for the task | -#### data.pipeline_tree DescriptionExample +#### data.pipeline_tree | Field | Type | Description | |-----------|----------|-----------| diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_periodic_task_list.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_periodic_task_list.md index d5474faa0..d7267ef2d 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_periodic_task_list.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_periodic_task_list.md @@ -14,7 +14,7 @@ Query periodic task for business ### Request Parameters Example -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -25,7 +25,7 @@ Query periodic task for business ### Return Result Example -```python +``` { "data": [ { @@ -63,7 +63,7 @@ Query periodic task for business } ``` -### Return Result Parameters DescriptionExample +### Return Result Description | Field | Type | Description | |-----------|----------|-----------| @@ -83,4 +83,3 @@ Query periodic task for business | enabled | bool | is the task enabled | | id | int | task id | | template_id | string | template id for the task | - diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_task_detail.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_task_detail.md new file mode 100644 index 000000000..e7d7aea33 --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_task_detail.md @@ -0,0 +1,333 @@ +### Functional description + +Query a task execution details + +### Request Parameters + +{{ common_args_desc }} + +#### Interface Parameters + +| Field | Type | Required | Description | +|---------------|------------|--------|------------------| +| bk_biz_id | string | YES | the business ID | +| task_id | string | YES | the task ID | + +### Request Parameters Example + +``` +{ + "bk_app_code": "esb_test", + "bk_app_secret": "xxx", + "bk_token": "xxx", + "bk_biz_id": "2", + "task_id": "10" +} +``` + +### Return Result Example + +``` +{ + "data": { + "creator": "admin", + "outputs": [ + { + "value": "1", + "key": "${job_script_type}", + "name": "type" + }, + { + "value": "127.0.0.1", + "key": "${IP}", + "name": "IP" + }, + { + "value": "0", + "key": "${EXIT}", + "name": "EXIT" + } + ], + "start_time": "2019-01-17 04:13:08", + "business_id": 2, + "create_time": "2019-01-17 04:13:03", + "business_name": "blueking", + "id": 10, + "constants": { + "${IP}": { + "source_tag": "var_ip_picker.ip_picker", + "source_info": {}, + "name": "IP", + "index": 2, + "custom_type": "ip", + "value": { + "var_ip_custom_value": "127.0.0.1", + "var_ip_method": "custom", + "var_ip_tree": [] + }, + "show_type": "show", + "source_type": "custom", + "validator": [], + "key": "${IP}", + "desc": "", + "validation": "", + "is_meta": false + }, + "${job_script_type}": { + "source_tag": "job_fast_execute_script.job_script_type", + "source_info": { + "node554316ea019a341f8c28cc6a7da9": [ + "job_script_type" + ] + }, + "name": "type", + "index": 0, + "custom_type": "", + "value": "1", + "show_type": "show", + "source_type": "component_inputs", + "key": "${job_script_type}", + "validation": "", + "desc": "" + }, + "${EXIT}": { + "source_tag": "", + "source_info": {}, + "name": "EXIT", + "index": 1, + "custom_type": "input", + "value": "0", + "show_type": "show", + "source_type": "custom", + "validator": [], + "key": "${EXIT}", + "validation": "^.+$", + "desc": "" + } + }, + "create_method": "app", + "elapsed_time": 7, + "ex_data": "", + "instance_name": "job_20190117121300", + "end_time": "2019-01-17 04:13:15", + "executor": "admin", + "template_id": "266", + "task_url": "http://bk_sops_host/taskflow/execute/3/?instance_id=15364", + "pipeline_tree": { + "activities": { + "node9b5ae13799d63e179f0ce3088b62": { + "outgoing": "line27bc7b4ccbcf37ddb9d1f6572a04", + "incoming": "line490caa49d2a03e64829693281032", + "name": "timing", + "error_ignorable": false, + "component": { + "code": "sleep_timer", + "data": { + "bk_timing": { + "hook": false, + "value": "2" + } + } + }, + "stage_name": "步骤1", + "can_retry": true, + "isSkipped": true, + "type": "ServiceActivity", + "optional": false, + "id": "node9b5ae13799d63e179f0ce3088b62", + "loop": null + }, + "node880ded556c6c3c269be3cedc64b6": { + "outgoing": "line490caa49d2a03e64829693281032", + "incoming": "lineb83161d6e0593ad68d9ec73a961b", + "name": "暂停", + "error_ignorable": false, + "component": { + "code": "pause_node", + "data": {} + }, + "stage_name": "步骤1", + "can_retry": true, + "isSkipped": true, + "type": "ServiceActivity", + "optional": true, + "id": "node880ded556c6c3c269be3cedc64b6", + "loop": null + } + }, + "end_event": { + "type": "EmptyEndEvent", + "outgoing": "", + "incoming": "line27bc7b4ccbcf37ddb9d1f6572a04", + "id": "node5c48f37aa9f0351e8b43ab6a2295", + "name": "" + }, + "outputs": [], + "flows": { + "line490caa49d2a03e64829693281032": { + "is_default": false, + "source": "node880ded556c6c3c269be3cedc64b6", + "id": "line490caa49d2a03e64829693281032", + "target": "node9b5ae13799d63e179f0ce3088b62" + }, + "lineb83161d6e0593ad68d9ec73a961b": { + "is_default": false, + "source": "noded383bc1d7387391f889c6bab18b8", + "id": "lineb83161d6e0593ad68d9ec73a961b", + "target": "node880ded556c6c3c269be3cedc64b6" + }, + "line27bc7b4ccbcf37ddb9d1f6572a04": { + "is_default": false, + "source": "node9b5ae13799d63e179f0ce3088b62", + "id": "line27bc7b4ccbcf37ddb9d1f6572a04", + "target": "node5c48f37aa9f0351e8b43ab6a2295" + } + }, + "gateways": {}, + "line": [ + { + "source": { + "id": "node9b5ae13799d63e179f0ce3088b62", + "arrow": "Right" + }, + "target": { + "id": "node5c48f37aa9f0351e8b43ab6a2295", + "arrow": "Left" + }, + "id": "line27bc7b4ccbcf37ddb9d1f6572a04" + }, + { + "source": { + "id": "node880ded556c6c3c269be3cedc64b6", + "arrow": "Right" + }, + "target": { + "id": "node9b5ae13799d63e179f0ce3088b62", + "arrow": "Left" + }, + "id": "line490caa49d2a03e64829693281032" + }, + { + "source": { + "id": "noded383bc1d7387391f889c6bab18b8", + "arrow": "Right" + }, + "id": "lineb83161d6e0593ad68d9ec73a961b", + "target": { + "id": "node880ded556c6c3c269be3cedc64b6", + "arrow": "Left" + } + } + ], + "start_event": { + "type": "EmptyStartEvent", + "outgoing": "lineb83161d6e0593ad68d9ec73a961b", + "incoming": "", + "id": "noded383bc1d7387391f889c6bab18b8", + "name": "" + }, + "id": "node7ef6970d06ad3bc092594cb5ec5f", + "constants": {}, + "location": [ + { + "stage_name": "步骤1", + "name": "暂停", + "y": 135, + "x": 300, + "type": "tasknode", + "id": "node880ded556c6c3c269be3cedc64b6" + }, + { + "y": 150, + "x": 1000, + "type": "endpoint", + "id": "node5c48f37aa9f0351e8b43ab6a2295" + }, + { + "stage_name": "步骤1", + "name": "timing", + "y": 135, + "x": 595, + "type": "tasknode", + "id": "node9b5ae13799d63e179f0ce3088b62" + }, + { + "y": 150, + "x": 80, + "type": "startpoint", + "id": "noded383bc1d7387391f889c6bab18b8" + } + ] + } + }, + "result": true +} +``` + +### Return Result Description + +| Field | Type | Description | +|-----------|----------|-----------| +| result | bool | true or false, indicate success or failure | +| data | dict | data returned when result is true, details are described below | +| message | string | error message returned when result is false | + + +#### data + +| Field | Type | Description | +|-----------|----------|-----------| +| id | int | the unique ID of task | +| name | string | the name of task | +| business_id | int | the business ID | +| business_name | string | the business name | +| template_id | int | the ID of flow used to create task | +| create_time | string | datetime when this task created | +| create_method | string | method how this task created | +| start_time | string | start time | +| finish_time | string | finish time | +| elapsed_time | int | elapsed time(seconds) | +| creator | string | person who created this task | +| executor | string | person who executed this task | +| constants | dict | global variables, details are described below | +| outputs | list | outputs info of this task,details are described below | +| task_url | str | task instance url | +| pipeline_tree | dict | task pipeline tree | + +#### data.constants.KEY + +KEY, the format is like ${key} + + +#### data.constants.VALUE +| Field | Type | Description | +| ------------ | ---------- | ------------------------------ | +| key | string | same with KEY | +| name | string | name | +| index | int | display order at the front end | +| desc | string | description | +| source_type | string | source of variable, custom mean manual variable, component_inputs means variables comes from task node inputs parameters, component_outputs means variables comes from task node outputs parameters | +| custom_type | string | custom type, which is not empty when source_type is custom, the value is input ,or textarea, or datetime, or int | +| source_tag | string | source tag and atom info, which is not empty when source_type is component_inputs or component_outputs | +| source_info | dict | source info about task node ID | + + +#### data.outputs[] +| Field | Type | Description | +| ------------ | ---------- | ------------------------------ | +| name | string | name of output variable | +| value | string、int、bool、dict、list | value | +| key | string | KEY | +| preset | bool | where to display in Standard Plugins | + +#### data.pipeline_tree + +| Field | Type | Description | +|-----------|----------|-----------| +| start_event | dict | start node | +| end_event | dict | end node | +| activities | dict | task node(atoms or subprocess)info | +| gateways | dict | gateways(parallel gateway、exclusive gateway、exclusive gateway)info | +| flows | dict | sequenceFlow(the line between nodes)info | +| constants | dict | global variables, details are described below | +| outputs | list | outputs info, indicate outputs field of global | diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_task_node_detail.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_task_node_detail.md new file mode 100644 index 000000000..4b6982d87 --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_task_node_detail.md @@ -0,0 +1,132 @@ +### Functional description + +Query a task node execution details + +### Request Parameters + +{{ common_args_desc }} + +#### Interface Parameters + +| Field | Type | Required | Description | +|---------------|------------|--------|------------------| +| bk_biz_id | string | YES | the business ID | +| task_id | string | YES | the task ID | +| node_id | string | YES | the node ID of task | +| component_code| string | NO | the code of Standard Plugin, this field is required when query a Standard Plugin node | +| subprocess_stack| string | NO | stack of SubProcess, format is json | + +### Request Parameters Example + +``` +{ + "bk_app_code": "esb_test", + "bk_app_secret": "xxx", + "bk_token": "xxx", + "bk_biz_id": "2", + "task_id": "10", + "node_id": "node0df0431f8f553925af01a94854bd" + "subprocess_stack": "[\"nodeaaa0ce51d2143aa9b0dbc27cb7df\"]", + "component_code": "job_fast_execute_script", +} +``` + +### Return Result Example + +``` +{ + "message": "", + "data": { + "inputs": { + "job_account": "root", + "job_script_timeout": "", + "job_script_source": "manual", + "job_script_list_public": "", + "job_content": "echo 0\nexit 0", + "job_script_type": "1", + "job_script_param": "", + "job_script_list_general": "", + "job_ip_list": "127.0.0.1" + }, + "retry": 0, + "name": "", + "finish_time": "2019-01-17 22:02:46 +0800", + "skip": false, + "start_time": "2019-01-17 22:02:37 +0800", + "children": {}, + "histories": [], + "ex_data": null, + "elapsed_time": 9, + "outputs": [ + { + "value": 407584, + "name": "task ID", + "key": "job_inst_id" + }, + { + "value": "", + "name": "link", + "key": "job_inst_url" + }, + { + "value": true, + "name": "result", + "key": "_result" + } + ], + "state": "FINISHED", + "version": "23ac8c29f62b3337aafcf1f538d277f8", + "error_ignorable": false, + "id": "node0df0431f8f553925af01a94854bd", + "loop": 1 + }, + "result": true +} +``` + +### Return Result Description + +| Field | Type | Description | +|-----------|----------|-----------| +| result | bool | true or false, indicate success or failure | +| data | dict | data returned when result is true, details are described below | +| message | string | error message returned when result is false | + +#### data + +| Field | Type | Description | +|-----------|----------|-----------| +| id | string | the unique ID of node | +| start_time | string | start time of last execution | +| finish_time | string | finish time of last execution | +| elapsed_time | int | elapsed time of last execution | +| state | string | execution status,CREATED,RUNNING,FAILED,NODE_SUSPENDED,SUSPENDED | +| skip | bool | skipped manually | +| retry | int | retry times | +| inputs | dict | inputs parameters, format is key:value | +| outputs | list | outputs info of this node,details are described below | +| ex_data | string | failure detail of this node,format is json or HTML、string | +| histories | list | retry records, details are described below | + +#### data.outputs[] +| Field | Type | Description | +| ------------ | ---------- | ------------------------------ | +| name | string | name of output variable | +| value | string、int、bool、dict、list | value | +| key | string | KEY | +| preset | bool | where to display in Standard Plugins | + + +#### data.histories[] +| 名称 | 类型 | 说明 | +| ------------ | ---------- | ------------------------------ | +| start_time | string | start time | +| finish_time | string | finish time | +| elapsed_time | int | elapsed time | +| state | string | execution status,CREATED,RUNNING,FAILED,NODE_SUSPENDED,SUSPENDED | +| skip | bool | skipped manually | +| retry | int | retry times | +| inputs | dict | inputs parameters, format is key:value | +| outputs | list | outputs info of this node,details are described below | +| ex_data | string | failure detail of this node,format is json or HTML、string | +| histories | list | retry records, details are described below | diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_task_status.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_task_status.md index 4b854c8e7..0dfb89bad 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_task_status.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_task_status.md @@ -15,7 +15,7 @@ Query a task or task node execution status ### Request Parameters Example -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -27,7 +27,7 @@ Query a task or task node execution status ### Return Result Example -```python +``` { "result": true, "data": { @@ -70,7 +70,7 @@ Query a task or task node execution status } ``` -### Return Result Parameters DescriptionExample +### Return Result Description | Field | Type | Description | |-----------|----------|-----------| @@ -89,6 +89,7 @@ Query a task or task node execution status | start_time | string | start time | | finish_time| string | finish time | | children | dict | task detail of children nodes, details are described below | +| name | string | node name | #### data.state diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_template_info.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_template_info.md index 520a9a13a..6d95568ad 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_template_info.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_template_info.md @@ -12,22 +12,24 @@ Query individual flow template details of the business |---------------|------------|--------|---------------| | bk_biz_id | string | YES | the business ID | | template_id | string | YES | the task ID | +| template_source | string | NO | source of flow,default value is business. business: from business, common: from common flow | ### Request Parameters Example -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", "bk_token": "xxx", "bk_biz_id": "1", - "template_id": "30" + "template_id": "30", + "template_source": "business", } ``` ### Return Result Example -```python +``` { "result": true, "data": { @@ -177,7 +179,7 @@ Query individual flow template details of the business } ``` -### Return Result Parameters DescriptionExample +### Return Result Description | Field | Type | Description | |-----------|----------|-----------| diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_template_list.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_template_list.md index 5cc496f90..27d778a65 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_template_list.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/get_template_list.md @@ -11,21 +11,23 @@ Query flow templates list of the business | Field | Type | Required | Description | |---------------|------------|--------|-------------------| | bk_biz_id | string | YES | the business ID | +| template_source | string | NO | source of flow,default value is business. business: from business, common: from common flow | ### Request Parameters Example -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", "bk_token": "xxx", - "bk_biz_id": "2" + "bk_biz_id": "2", + "template_source": "business", } ``` ### Return Result Example -```python +``` { "result": true, "data": [ @@ -66,7 +68,7 @@ Query flow templates list of the business } ``` -### Return Result Parameters DescriptionExample +### Return Result Description | Field | Type | Description | |-----------|----------|-----------| diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/import_common_template.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/import_common_template.md new file mode 100644 index 000000000..380e8cce1 --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/import_common_template.md @@ -0,0 +1,52 @@ +### Functional description + +import common flow template + +### Request Parameters + +{{ common_args_desc }} + +#### Interface Parameters + +| Field | Type | Required | Description | +| ------------ | ------------ | ------ | ---------------- | +| template_data | string | YES | flow data, the content of file which download from bk-sops - common templates - export | +| override | bool | NO | whether to override flows which has same ID | | + +### Request Parameters Example + +``` +{ + "bk_app_code": "esb_test", + "bk_app_secret": "xxx", + "bk_token": "xxx", + "template_data": "xxx", + "override": true, +} +``` + +### Return Result Example + +``` +{ + "message": "Successfully imported 2 common flows", + "data": { + "count": 2 + }, + "result": true +} +``` + +### Return Result Description + +| Field | Type | Description | +| ------------ | ---------- | ------------------------------ | +| result | bool | true or false, indicate success or failure | +| message | string | error message returned when result is false | +| data | dict | return data | + +#### data + +| Field | Type | Description | +| ------------ | ---------- | ------------------------------ | +| count | int | the number of flows had been imported | diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/modify_constants_for_periodic_task.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/modify_constants_for_periodic_task.md index 894a47ba1..186da7555 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/modify_constants_for_periodic_task.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/modify_constants_for_periodic_task.md @@ -24,7 +24,7 @@ constant value ### Request Parameters Example -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -37,7 +37,7 @@ constant value ### Return Result Example -```python +``` { "data": { "${bk_timing}": { @@ -62,7 +62,7 @@ constant value } ``` -### Return Result Parameters DescriptionExample +### Return Result Description | Field | Type | Description | |-----------|----------|-----------| @@ -86,4 +86,3 @@ KEY, the format is like ${key} | custom_type | string | custom type, which is not empty when source_type is custom, the value is input ,or textarea, or datetime, or int | | source_tag | string | source tag and atom info, which is not empty when source_type is component_inputs or component_outputs | | source_info | dict | source info about task node ID | - diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/modify_cron_for_periodic_task.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/modify_cron_for_periodic_task.md index 9235a23c9..c1ffc516b 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/modify_cron_for_periodic_task.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/modify_cron_for_periodic_task.md @@ -12,7 +12,7 @@ modify crontab for periodic task |---------------|------------|--------|------------------| | task_id | string | YES | task ID | | bk_biz_id | string | YES | business ID | -| cron | object | YES | crontab object | +| cron | dict | YES | crontab dict | #### cron @@ -26,7 +26,7 @@ modify crontab for periodic task ### Request Parameters Example -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -39,7 +39,7 @@ modify crontab for periodic task ### Return Result Example -```python +``` { "data": { "cron": "*/1 15 * * * (m/h/d/dM/MY)" @@ -48,7 +48,7 @@ modify crontab for periodic task } ``` -### Return Result Parameters DescriptionExample +### Return Result Description | Field | Type | Description | |-----------|----------|-----------| @@ -61,4 +61,3 @@ modify crontab for periodic task | Field | Type | Description | | ------------ | ---------- | ------------------------------ | | cron | string | crontab expression | - diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/node_callback.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/node_callback.md new file mode 100644 index 000000000..2bcc5a1f9 --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/node_callback.md @@ -0,0 +1,49 @@ +### Functional description + +callback specific node + +### Request Parameters + +{{ common_args_desc }} + +#### Interface Parameters + +| Field | Type | Required | Description | +| ------------ | ------------ | ------ | ---------------- | +| bk_biz_id | string | YES | the business ID | +| task_id | string | YES | the task ID | +| node_id | string | YES | node id | +| callback_data | dict | NO | callback data | | + +### Request Parameters Example + +``` +import requests +kwargs = { + "app_code": "app_code", + "app_secret": "app_secret", + "access_token": "access_token", + "bk_biz_id": "2", + "task_id": "10", + "node_id": "node0df0431f8f553925af01a94854bd", + "callback_data": {"data": "data"}, +} +response = requests.get("http://{stageVariables.domain}/apigw/node_callback/10/2/", kwargs) +result = response.json() +``` + +### Return Result Example + +``` +{ + "message": "success", + "result": true +} +``` + +### Return Result Description + +| Field | Type | Description | +| ------------ | ---------- | ------------------------------ | +| result | bool | true or false, indicate success or failure | +| message | string | error message returned when result is false | diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/operate_task.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/operate_task.md index 08a2ddeec..0b590b99a 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/operate_task.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/operate_task.md @@ -25,7 +25,7 @@ Task actions such as start, pause, resume, revoke, etc. ### Request Parameters Example -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -38,14 +38,14 @@ Task actions such as start, pause, resume, revoke, etc. ### Return Result Example -```python +``` { "result": true, "data": {} } ``` -### Return Result Parameters DescriptionExample +### Return Result Description | Field | Type | Description | |-----------|----------|-----------| diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/query_task_count.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/query_task_count.md index a6380c42b..103169022 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/query_task_count.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/query_task_count.md @@ -68,7 +68,7 @@ Query task instance classification statistics } ``` -### Return Result Parameters DescriptionExample +### Return Result Description | Field | Type | Description | |-----------|----------|-----------| @@ -83,7 +83,7 @@ Query task instance classification statistics | total | int | total number of tasks obtained by filter criteria | | groups | list | sort statistic details by filter criteria | -#### data.groups +#### data.groups[] | Field | Type | Description | |-----------|----------|-----------| | code | string | classification statistic type coding | diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/set_periodic_task_enabled.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/set_periodic_task_enabled.md index 8db29dafa..00806ed9f 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/set_periodic_task_enabled.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/set_periodic_task_enabled.md @@ -17,7 +17,7 @@ modify task activation status ### Request Parameters Example -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -30,7 +30,7 @@ modify task activation status ### Return Result Example -```python +``` { "data": { "enabled": false @@ -39,7 +39,7 @@ modify task activation status } ``` -### Return Result Parameters DescriptionExample +### Return Result Description | Field | Type | Description | |-----------|----------|-----------| @@ -52,5 +52,3 @@ modify task activation status | Field | Type | Description | | ------------ | ---------- | ------------------------------ | | enabled | bool | whether the task is activate | - - diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/start_task.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/start_task.md index 0d874c7f2..5f2d57fd0 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/en/start_task.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/en/start_task.md @@ -15,7 +15,7 @@ Start a task ### Request Parameters Example -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -27,14 +27,14 @@ Start a task ### Return Result Example -```python +``` { "result": true, "data": {} } ``` -### Return Result Parameters DescriptionExample +### Return Result Description | Field | Type | Description | |-----------|----------|-----------| diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/create_periodic_task.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/create_periodic_task.md index d6eeade9f..63c7abfe3 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/create_periodic_task.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/create_periodic_task.md @@ -13,9 +13,9 @@ | template_id | string | 是 | 用于创建任务的模板ID | | bk_biz_id | string | 是 | 任务所属业务ID | | name | string | 是 | 要创建的周期任务名称 | -| cron | object | 是 | 要创建的周期任务调度策略 | -| constants | object | 否 | 任务全局参数,详细信息见下面说明 | -| exclude_task_nodes_id | array | 否 | 跳过执行的节点ID列表 | +| cron | dict | 是 | 要创建的周期任务调度策略 | +| constants | dict | 否 | 任务全局参数,详细信息见下面说明 | +| exclude_task_nodes_id | list | 否 | 跳过执行的节点ID列表 | #### constants.KEY @@ -37,7 +37,7 @@ ### 请求参数示例 -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -53,7 +53,7 @@ ### 返回结果示例 -```python +``` { "message": "", "data": { @@ -216,7 +216,7 @@ | data | dict | result=true 时成功数据,详细信息请见下面说明 | | message | string | result=false 时错误信息 | -#### data 说明 +#### data | 名称 | 类型 | 说明 | | ------------ | ---------- | ------------------------------ | @@ -228,10 +228,10 @@ | enabled | bool | 是否激活 | | id | int | 周期任务 ID | | template_id | string | 用于创建该任务的模板 ID | -| form | object | 该周期任务的参数表单对象 | -| pipeline_tree | object | 该周期任务的实例树 | +| form | dict | 该周期任务的参数表单对象 | +| pipeline_tree | dict | 该周期任务的实例树 | -#### data.pipeline_tree 说明 +#### data.pipeline_tree | 名称 | 类型 | 说明 | | ------------ | ---------- | ------------------------------ | @@ -243,12 +243,11 @@ | constants | dict | 全局变量信息,详情见下面 | | outputs | list | 模板输出信息,标记 constants 中的输出字段 | -#### data.form, data.pipeline_tree.constants 说明 +#### data.form.KEY, data.pipeline_tree.constants.KEY -KEY: 全局变量 KEY,${key} 格式 -VALUE: +#### data.form.VALUE, data.pipeline_tree.constants.VALUE | 名称 | 类型 | 说明 | | ------------ | ---------- | ------------------------------ | @@ -258,5 +257,5 @@ VALUE: | desc | string | 变量说明 | | source_type | string | 变量来源, 取值范围 custom: 自定义变量,component_inputs: 从原子输入参数勾选,component_outputs:从原子输出结果中勾选 | | custom_type | string | source_type=custom 时有效,自定义变量类型, 取值范围 input: 输入框,textarea: 文本框,datetime: 日期时间,int: 整数| -| source_tag | string | source_type=component_inputs|component_outputs 时有效,变量的来源原子 | -| source_info | dict | source_type=component_inputs|component_outputs 时有效,变量的来源节点信息 | +| source_tag | string | source_type=component_inputs/component_outputs 时有效,变量的来源原子 | +| source_info | dict | source_type=component_inputs/component_outputs 时有效,变量的来源节点信息 | diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/create_task.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/create_task.md index 17aed6978..ec4455b61 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/create_task.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/create_task.md @@ -12,9 +12,11 @@ |---------------|------------|--------|------------------| | bk_biz_id | string | 是 | 模板所属业务ID | | template_id | string | 是 | 模板ID | +| template_source | string | 否 | 流程模板来源,business:默认值,业务流程,common:公共流程 | | name | string | 是 | 任务名称 | | flow_type | string | 否 | 任务流程类型,common: 常规流程,common_func:职能化流程 | | constants | dict | 否 | 任务全局参数,详细信息见下面说明 | +| exclude_task_nodes_id | list | 否 | 跳过执行的节点ID列表 | #### constants.KEY @@ -26,7 +28,7 @@ ### 请求参数示例 -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -43,11 +45,158 @@ ### 返回结果示例 -```python +``` { "result": true, "data": { - "task_id": 10 + "task_id": 10, + "task_url": "http://bk_sops_host/taskflow/execute/3/?instance_id=15364", + "pipeline_tree": { + "activities": { + "node9b5ae13799d63e179f0ce3088b62": { + "outgoing": "line27bc7b4ccbcf37ddb9d1f6572a04", + "incoming": "line490caa49d2a03e64829693281032", + "name": "timing", + "error_ignorable": false, + "component": { + "code": "sleep_timer", + "data": { + "bk_timing": { + "hook": false, + "value": "2" + } + } + }, + "stage_name": "步骤1", + "can_retry": true, + "isSkipped": true, + "type": "ServiceActivity", + "optional": false, + "id": "node9b5ae13799d63e179f0ce3088b62", + "loop": null + }, + "node880ded556c6c3c269be3cedc64b6": { + "outgoing": "line490caa49d2a03e64829693281032", + "incoming": "lineb83161d6e0593ad68d9ec73a961b", + "name": "暂停", + "error_ignorable": false, + "component": { + "code": "pause_node", + "data": {} + }, + "stage_name": "步骤1", + "can_retry": true, + "isSkipped": true, + "type": "ServiceActivity", + "optional": true, + "id": "node880ded556c6c3c269be3cedc64b6", + "loop": null + } + }, + "end_event": { + "type": "EmptyEndEvent", + "outgoing": "", + "incoming": "line27bc7b4ccbcf37ddb9d1f6572a04", + "id": "node5c48f37aa9f0351e8b43ab6a2295", + "name": "" + }, + "outputs": [], + "flows": { + "line490caa49d2a03e64829693281032": { + "is_default": false, + "source": "node880ded556c6c3c269be3cedc64b6", + "id": "line490caa49d2a03e64829693281032", + "target": "node9b5ae13799d63e179f0ce3088b62" + }, + "lineb83161d6e0593ad68d9ec73a961b": { + "is_default": false, + "source": "noded383bc1d7387391f889c6bab18b8", + "id": "lineb83161d6e0593ad68d9ec73a961b", + "target": "node880ded556c6c3c269be3cedc64b6" + }, + "line27bc7b4ccbcf37ddb9d1f6572a04": { + "is_default": false, + "source": "node9b5ae13799d63e179f0ce3088b62", + "id": "line27bc7b4ccbcf37ddb9d1f6572a04", + "target": "node5c48f37aa9f0351e8b43ab6a2295" + } + }, + "gateways": {}, + "line": [ + { + "source": { + "id": "node9b5ae13799d63e179f0ce3088b62", + "arrow": "Right" + }, + "target": { + "id": "node5c48f37aa9f0351e8b43ab6a2295", + "arrow": "Left" + }, + "id": "line27bc7b4ccbcf37ddb9d1f6572a04" + }, + { + "source": { + "id": "node880ded556c6c3c269be3cedc64b6", + "arrow": "Right" + }, + "target": { + "id": "node9b5ae13799d63e179f0ce3088b62", + "arrow": "Left" + }, + "id": "line490caa49d2a03e64829693281032" + }, + { + "source": { + "id": "noded383bc1d7387391f889c6bab18b8", + "arrow": "Right" + }, + "id": "lineb83161d6e0593ad68d9ec73a961b", + "target": { + "id": "node880ded556c6c3c269be3cedc64b6", + "arrow": "Left" + } + } + ], + "start_event": { + "type": "EmptyStartEvent", + "outgoing": "lineb83161d6e0593ad68d9ec73a961b", + "incoming": "", + "id": "noded383bc1d7387391f889c6bab18b8", + "name": "" + }, + "id": "node7ef6970d06ad3bc092594cb5ec5f", + "constants": {}, + "location": [ + { + "stage_name": "步骤1", + "name": "暂停", + "y": 135, + "x": 300, + "type": "tasknode", + "id": "node880ded556c6c3c269be3cedc64b6" + }, + { + "y": 150, + "x": 1000, + "type": "endpoint", + "id": "node5c48f37aa9f0351e8b43ab6a2295" + }, + { + "stage_name": "步骤1", + "name": "timing", + "y": 135, + "x": 595, + "type": "tasknode", + "id": "node9b5ae13799d63e179f0ce3088b62" + }, + { + "y": 150, + "x": 80, + "type": "startpoint", + "id": "noded383bc1d7387391f889c6bab18b8" + } + ] + } } } ``` @@ -60,8 +209,39 @@ | data | dict | result=true 时成功数据,详细信息请见下面说明 | | message | string | result=false 时错误信息 | -#### data 说明 +#### data | 字段 | 类型 | 描述 | |-----------|----------|-----------| | task_id | int | 任务实例ID | +| task_url | str | 任务实例链接 | +| pipeline_tree | dict | 任务实例树 | + +#### data.pipeline_tree + +| 字段 | 类型 | 描述 | +|-----------|----------|-----------| +| start_event | dict | 开始节点信息 | +| end_event | dict | 结束节点信息 | +| activities | dict | 任务节点(原子和子流程)信息 | +| gateways | dict | 网关节点(并行网关、分支网关和汇聚网关)信息 | +| flows | dict | 顺序流(节点连线)信息 | +| constants | dict | 全局变量信息,详情见下面 | +| outputs | list | 模板输出信息,标记 constants 中的输出字段 | + +#### data.pipeline_tree.constants.KEY + +全局变量 KEY,${key} 格式 + +#### data.pipeline_tree.constants.VALUE + +| 名称 | 类型 | 说明 | +| ------------ | ---------- | ------------------------------ | +| key | string | 同 KEY | +| name | string | 变量名字 | +| index | int | 变量在模板中的显示顺序 | +| desc | string | 变量说明 | +| source_type | string | 变量来源, 取值范围 custom: 自定义变量,component_inputs: 从原子输入参数勾选,component_outputs:从原子输出结果中勾选 | +| custom_type | string | source_type=custom 时有效,自定义变量类型, 取值范围 input: 输入框,textarea: 文本框,datetime: 日期时间,int: 整数| +| source_tag | string | source_type=component_inputs/component_outputs 时有效,变量的来源原子 | +| source_info | dict | source_type=component_inputs/component_outputs 时有效,变量的来源节点信息 | diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_periodic_task_info.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_periodic_task_info.md index 83f3d4bba..08afe2b0c 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_periodic_task_info.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_periodic_task_info.md @@ -15,7 +15,7 @@ ### 请求参数示例 -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -27,7 +27,7 @@ ### 返回结果示例 -```python +``` { "message": "", "data": { @@ -242,10 +242,10 @@ | enabled | bool | 是否激活 | | id | int | 周期任务 ID | | template_id | string | 用于创建该任务的模板 ID | -| form | object | 该周期任务的参数表单对象 | -| pipeline_tree | object | 该周期任务的实例树 | +| form | dict | 该周期任务的参数表单对象 | +| pipeline_tree | dict | 该周期任务的实例树 | -#### data.pipeline_tree 说明 +#### data.pipeline_tree | 名称 | 类型 | 说明 | | ------------ | ---------- | ------------------------------ | | start_event | dict | 开始节点信息 | @@ -270,5 +270,5 @@ | desc | string | 变量说明 | | source_type | string | 变量来源, 取值范围 custom: 自定义变量,component_inputs: 从原子输入参数勾选,component_outputs:从原子输出结果中勾选 | | custom_type | string | source_type=custom 时有效,自定义变量类型, 取值范围 input: 输入框,textarea: 文本框,datetime: 日期时间,int: 整数| -| source_tag | string | source_type=component_inputs|component_outputs 时有效,变量的来源原子 | -| source_info | dict | source_type=component_inputs|component_outputs 时有效,变量的来源节点信息 | \ No newline at end of file +| source_tag | string | source_type=component_inputs/component_outputs 时有效,变量的来源原子 | +| source_info | dict | source_type=component_inputs/component_outputs 时有效,变量的来源节点信息 | diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_periodic_task_list.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_periodic_task_list.md index a11c81b4b..9401568b9 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_periodic_task_list.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_periodic_task_list.md @@ -14,7 +14,7 @@ ### 请求参数示例 -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -25,7 +25,7 @@ ### 返回结果示例 -```python +``` { "data": [ { @@ -83,4 +83,3 @@ | enabled | bool | 是否激活 | | id | int | 周期任务ID | | template_id | string | 用于创建该任务的模板ID | - diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_task_detail.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_task_detail.md new file mode 100644 index 000000000..8a1354d2e --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_task_detail.md @@ -0,0 +1,332 @@ +### 功能描述 + +查询任务执行详情 + +### 请求参数 + +{{ common_args_desc }} + +#### 接口参数 + +| 字段 | 类型 | 必选 | 描述 | +|---------------|------------|--------|------------------| +| bk_biz_id | string | 是 | 所属业务ID | +| task_id | string | 是 | 任务ID | + +### 请求参数示例 + +``` +{ + "bk_app_code": "esb_test", + "bk_app_secret": "xxx", + "bk_token": "xxx", + "bk_biz_id": "2", + "task_id": "10" +} +``` + +### 返回结果示例 + +``` +{ + "data": { + "creator": "admin", + "outputs": [ + { + "value": "1", + "key": "${job_script_type}", + "name": "脚本类型" + }, + { + "value": "127.0.0.1", + "key": "${IP}", + "name": "IP" + }, + { + "value": "0", + "key": "${EXIT}", + "name": "EXIT" + } + ], + "start_time": "2019-01-17 04:13:08", + "business_id": 2, + "create_time": "2019-01-17 04:13:03", + "business_name": "蓝鲸", + "id": 10, + "constants": { + "${IP}": { + "source_tag": "var_ip_picker.ip_picker", + "source_info": {}, + "name": "IP", + "index": 2, + "custom_type": "ip", + "value": { + "var_ip_custom_value": "127.0.0.1", + "var_ip_method": "custom", + "var_ip_tree": [] + }, + "show_type": "show", + "source_type": "custom", + "validator": [], + "key": "${IP}", + "desc": "", + "validation": "", + "is_meta": false + }, + "${job_script_type}": { + "source_tag": "job_fast_execute_script.job_script_type", + "source_info": { + "node554316ea019a341f8c28cc6a7da9": [ + "job_script_type" + ] + }, + "name": "脚本类型", + "index": 0, + "custom_type": "", + "value": "1", + "show_type": "show", + "source_type": "component_inputs", + "key": "${job_script_type}", + "validation": "", + "desc": "" + }, + "${EXIT}": { + "source_tag": "", + "source_info": {}, + "name": "EXIT", + "index": 1, + "custom_type": "input", + "value": "0", + "show_type": "show", + "source_type": "custom", + "validator": [], + "key": "${EXIT}", + "validation": "^.+$", + "desc": "" + } + }, + "create_method": "app", + "elapsed_time": 7, + "ex_data": "", + "instance_name": "job输出变量测试_20190117121300", + "end_time": "2019-01-17 04:13:15", + "executor": "admin", + "template_id": "266", + "task_url": "http://bk_sops_host/taskflow/execute/3/?instance_id=15364", + "pipeline_tree": { + "activities": { + "node9b5ae13799d63e179f0ce3088b62": { + "outgoing": "line27bc7b4ccbcf37ddb9d1f6572a04", + "incoming": "line490caa49d2a03e64829693281032", + "name": "timing", + "error_ignorable": false, + "component": { + "code": "sleep_timer", + "data": { + "bk_timing": { + "hook": false, + "value": "2" + } + } + }, + "stage_name": "步骤1", + "can_retry": true, + "isSkipped": true, + "type": "ServiceActivity", + "optional": false, + "id": "node9b5ae13799d63e179f0ce3088b62", + "loop": null + }, + "node880ded556c6c3c269be3cedc64b6": { + "outgoing": "line490caa49d2a03e64829693281032", + "incoming": "lineb83161d6e0593ad68d9ec73a961b", + "name": "暂停", + "error_ignorable": false, + "component": { + "code": "pause_node", + "data": {} + }, + "stage_name": "步骤1", + "can_retry": true, + "isSkipped": true, + "type": "ServiceActivity", + "optional": true, + "id": "node880ded556c6c3c269be3cedc64b6", + "loop": null + } + }, + "end_event": { + "type": "EmptyEndEvent", + "outgoing": "", + "incoming": "line27bc7b4ccbcf37ddb9d1f6572a04", + "id": "node5c48f37aa9f0351e8b43ab6a2295", + "name": "" + }, + "outputs": [], + "flows": { + "line490caa49d2a03e64829693281032": { + "is_default": false, + "source": "node880ded556c6c3c269be3cedc64b6", + "id": "line490caa49d2a03e64829693281032", + "target": "node9b5ae13799d63e179f0ce3088b62" + }, + "lineb83161d6e0593ad68d9ec73a961b": { + "is_default": false, + "source": "noded383bc1d7387391f889c6bab18b8", + "id": "lineb83161d6e0593ad68d9ec73a961b", + "target": "node880ded556c6c3c269be3cedc64b6" + }, + "line27bc7b4ccbcf37ddb9d1f6572a04": { + "is_default": false, + "source": "node9b5ae13799d63e179f0ce3088b62", + "id": "line27bc7b4ccbcf37ddb9d1f6572a04", + "target": "node5c48f37aa9f0351e8b43ab6a2295" + } + }, + "gateways": {}, + "line": [ + { + "source": { + "id": "node9b5ae13799d63e179f0ce3088b62", + "arrow": "Right" + }, + "target": { + "id": "node5c48f37aa9f0351e8b43ab6a2295", + "arrow": "Left" + }, + "id": "line27bc7b4ccbcf37ddb9d1f6572a04" + }, + { + "source": { + "id": "node880ded556c6c3c269be3cedc64b6", + "arrow": "Right" + }, + "target": { + "id": "node9b5ae13799d63e179f0ce3088b62", + "arrow": "Left" + }, + "id": "line490caa49d2a03e64829693281032" + }, + { + "source": { + "id": "noded383bc1d7387391f889c6bab18b8", + "arrow": "Right" + }, + "id": "lineb83161d6e0593ad68d9ec73a961b", + "target": { + "id": "node880ded556c6c3c269be3cedc64b6", + "arrow": "Left" + } + } + ], + "start_event": { + "type": "EmptyStartEvent", + "outgoing": "lineb83161d6e0593ad68d9ec73a961b", + "incoming": "", + "id": "noded383bc1d7387391f889c6bab18b8", + "name": "" + }, + "id": "node7ef6970d06ad3bc092594cb5ec5f", + "constants": {}, + "location": [ + { + "stage_name": "步骤1", + "name": "暂停", + "y": 135, + "x": 300, + "type": "tasknode", + "id": "node880ded556c6c3c269be3cedc64b6" + }, + { + "y": 150, + "x": 1000, + "type": "endpoint", + "id": "node5c48f37aa9f0351e8b43ab6a2295" + }, + { + "stage_name": "步骤1", + "name": "timing", + "y": 135, + "x": 595, + "type": "tasknode", + "id": "node9b5ae13799d63e179f0ce3088b62" + }, + { + "y": 150, + "x": 80, + "type": "startpoint", + "id": "noded383bc1d7387391f889c6bab18b8" + } + ] + } + }, + "result": true +} +``` + +### 返回结果参数说明 + +| 字段 | 类型 | 描述 | +|-----------|----------|-----------| +| result | bool | true/false 查询成功与否 | +| data | dict | result=true 时返回数据,详细信息见下面说明 | +| message | string | result=false 时错误信息 | + +#### data + +| 字段 | 类型 | 描述 | +|-----------|----------|-----------| +| id | int | 任务 ID,即 task_id | +| name | string | 任务名称 | +| business_id | int | 所属业务 ID | +| business_name | string | 所属业务名称 | +| template_id | int | 创建任务所用的流程模板 ID | +| create_time | string | 任务创建时间 | +| create_method | string | 任务创建方式 | +| start_time | string | 任务执行时间 | +| finish_time | string | 任务完成时间 | +| elapsed_time | int | 任务执行耗时(秒) | +| creator | string | 任务创建人 | +| executor | string | 任务执行人 | +| constants | dict | 输入的全局变量,详情见下面说明 | +| outputs | list | 任务输出参数,详情见下面说明 | +| task_url | str | 任务实例链接 | +| pipeline_tree | dict | 任务实例树 | + +#### data.constants.KEY + +全局变量 KEY,${key} 格式 + + +#### data.constants.VALUE +| 字段 | 类型 | 描述 | +| ------------ | ---------- | ------------------------------ | +| key | string | 同 KEY | +| name | string | 变量名字 | +| index | int | 变量在模板中的显示顺序 | +| desc | string | 变量说明 | +| source_type | string | 变量来源, 取值范围 custom: 自定义变量,component_inputs: 从标准插件输入参数勾选,component_outputs:从标准插件输出结果中勾选 | +| custom_type | string | source_type=custom 时有效,自定义变量类型, 取值范围 input: 输入框,textarea: 文本框,datetime: 日期时间,int: 整数| +| source_tag | string | source_type=component_inputs/component_outputs 时有效,变量的来源标准插件 | +| source_info | dict | source_type=component_inputs/component_outputs 时有效,变量的来源节点信息 | + + +#### data.outputs[] +| 字段 | 类型 | 描述 | +| ------------ | ---------- | ------------------------------ | +| name | string | 输出参数名称 | +| value | string、int、bool、dict、list | 输出参数值 | +| key | string | 输出参数 KEY | +| preset | bool | 是否是标准插件定义中预设输出变量 | + +#### data.pipeline_tree + +| 字段 | 类型 | 描述 | +|-----------|----------|-----------| +| start_event | dict | 开始节点信息 | +| end_event | dict | 结束节点信息 | +| activities | dict | 任务节点(原子和子流程)信息 | +| gateways | dict | 网关节点(并行网关、分支网关和汇聚网关)信息 | +| flows | dict | 顺序流(节点连线)信息 | +| constants | dict | 全局变量信息,详情见下面 | +| outputs | list | 模板输出信息,标记 constants 中的输出字段 | diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_task_node_detail.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_task_node_detail.md new file mode 100644 index 000000000..6d81415cc --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_task_node_detail.md @@ -0,0 +1,132 @@ +### 功能描述 + +查询任务节点执行详情 + +### 请求参数 + +{{ common_args_desc }} + +#### 接口参数 + +| 字段 | 类型 | 必选 | 描述 | +|---------------|------------|--------|------------------| +| bk_biz_id | string | 是 | 所属业务ID | +| task_id | string | 是 | 任务ID | +| node_id | string | 是 | 节点 ID | +| component_code| string | 否 | 标准插件编码,请求标准插件执行详情必填 | +| subprocess_stack| string | 否 | 子流程堆栈,json 格式的列表 | + +### 请求参数示例 + +``` +{ + "bk_app_code": "esb_test", + "bk_app_secret": "xxx", + "bk_token": "xxx", + "bk_biz_id": "2", + "task_id": "10", + "node_id": "node0df0431f8f553925af01a94854bd" + "subprocess_stack": "[\"nodeaaa0ce51d2143aa9b0dbc27cb7df\"]", + "component_code": "job_fast_execute_script", +} +``` + +### 返回结果示例 + +``` +{ + "message": "", + "data": { + "inputs": { + "job_account": "root", + "job_script_timeout": "", + "job_script_source": "manual", + "job_script_list_public": "", + "job_content": "echo 0\nexit 0", + "job_script_type": "1", + "job_script_param": "", + "job_script_list_general": "", + "job_ip_list": "127.0.0.1" + }, + "retry": 0, + "name": "", + "finish_time": "2019-01-17 22:02:46 +0800", + "skip": false, + "start_time": "2019-01-17 22:02:37 +0800", + "children": {}, + "histories": [], + "ex_data": null, + "elapsed_time": 9, + "outputs": [ + { + "value": 407584, + "name": "JOB任务ID", + "key": "job_inst_id" + }, + { + "value": "", + "name": "JOB任务链接", + "key": "job_inst_url" + }, + { + "value": true, + "name": "执行结果", + "key": "_result" + } + ], + "state": "FINISHED", + "version": "23ac8c29f62b3337aafcf1f538d277f8", + "error_ignorable": false, + "id": "node0df0431f8f553925af01a94854bd", + "loop": 1 + }, + "result": true +} +``` + +### 返回结果参数说明 + +| 字段 | 类型 | 描述 | +|-----------|----------|-----------| +| result | bool | true/false 查询成功与否 | +| data | dict | result=true 时返回数据,详细信息见下面说明 | +| message | string | result=false 时错误信息 | + +#### data + +| 字段 | 类型 | 描述 | +|-----------|----------|-----------| +| id | string | 节点 ID | +| start_time | string | 最后一次执行开始时间 | +| finish_time | string | 最后一次执行结束时间 | +| elapsed_time | int | 最后一次执行耗时,单位秒 | +| state | string | 最后一次执行状态,CREATED:未执行,RUNNING:执行中,FAILED:失败,NODE_SUSPENDED:暂停,SUSPENDED:成功 | +| skip | bool | 是否手动跳过 | +| retry | int | 重试次数 | +| inputs | dict | 输入参数,key:value格式 | +| outputs | list | 输出参数,详情见下面说明 | +| ex_data | string | 节点执行失败详情,json字符串或者HTML字符串、普通字符串 | +| histories | list | 重试记录详情,详情见下面说明 | + +#### outputs[] +| 名称 | 类型 | 说明 | +| ------------ | ---------- | ------------------------------ | +| name | string | 输出字段 | +| value | string、int、bool、dict、list | 输出参数值 | +| key | string | 输出参数 KEY | +| preset | bool | 是否是标准插件定义中预设输出变量 | + + +#### histories[] +| 名称 | 类型 | 说明 | +| ------------ | ---------- | ------------------------------ | +| start_time | string | 执行开始时间 | +| finish_time | string | 执行结束时间 | +| elapsed_time | int | 执行耗时 | +| state | string | 执行状态,CREATED:未执行,RUNNING:执行中,FAILED:失败,NODE_SUSPENDED:暂停,SUSPENDED:成功 | +| skip | bool | 是否手动跳过 | +| retry | int | 重试次数 | +| histories | list | 重试记录详情,详情见下面说明 | +| inputs | dict | 输入参数,key:value格式 | +| outputs | dict | 输出参数,key:value格式 | +| ex_data | string | 节点执行失败详情,json字符串或者HTML字符串、普通字符串 | diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_task_status.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_task_status.md index 1ce478b24..a18013843 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_task_status.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_task_status.md @@ -15,7 +15,7 @@ ### 请求参数示例 -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -27,7 +27,7 @@ ### 返回结果示例 -```python +``` { "result": true, "data": { @@ -89,6 +89,7 @@ | start_time | string | 任务或节点执行开始时间 | | finish_time | string | 任务或节点执行结束时间 | | children | dict | 任务节点执行详情,详细信息见下面说明 | +| name | string | 节点名称 | #### data.state @@ -102,7 +103,7 @@ | FINISHED | 已完成 | #### data.children.KEY -任务节点 执行态ID +任务节点执行态ID #### data.children.VALUE 同 data 格式 diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_template_info.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_template_info.md index 835d6314f..a08d66b5f 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_template_info.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_template_info.md @@ -12,22 +12,24 @@ |---------------|------------|--------|---------------| | bk_biz_id | string | 是 | 模板所属业务ID | | template_id | string | 是 | 模板ID | +| template_source | string | 否 | 流程模板来源,business:默认值,业务流程,common:公共流程 | ### 请求参数示例 -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", "bk_token": "xxx", "bk_biz_id": "1", - "template_id": "30" + "template_id": "30", + "template_source": "business", } ``` ### 返回结果示例 -```python +``` { "result": true, "data": { diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_template_list.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_template_list.md index a325766a6..a9fedf380 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_template_list.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/get_template_list.md @@ -11,21 +11,23 @@ | 字段 | 类型 | 必选 | 描述 | |---------------|------------|--------|-------------------| | bk_biz_id | string | 是 | 模板所属业务ID | +| template_source | string | 否 | 流程模板来源,business:默认值,业务流程,common:公共流程 | ### 请求参数示例 -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", "bk_token": "xxx", - "bk_biz_id": "2" + "bk_biz_id": "2", + "template_source": "business", } ``` ### 返回结果示例 -```python +``` { "result": true, "data": [ diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/import_common_template.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/import_common_template.md new file mode 100644 index 000000000..0bb03461d --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/import_common_template.md @@ -0,0 +1,52 @@ +### 功能描述 + +导入公共流程 + +### 请求参数 + +{{ common_args_desc }} + +#### 接口参数 + +| 字段 | 参数类型 | 必须 | 参数说明 | +| ------------ | ------------ | ------ | ---------------- | +| template_data | string | 是 | 公共流程数据,即从标准运维 - 公共流程 - 导出功能下载的文件的内容 | +| override | bool | 否 | 是否覆盖 ID 相同的流程 | | + +### 请求参数示例 + +``` +{ + "bk_app_code": "esb_test", + "bk_app_secret": "xxx", + "bk_token": "xxx", + "template_data": "xxx", + "override": true, +} +``` + +### 返回结果示例 + +``` +{ + "message": "Successfully imported 2 common flows", + "data": { + "count": 2 + }, + "result": true +} +``` + +### 返回结果参数说明 + +| 名称 | 类型 | 说明 | +| ------------ | ---------- | ------------------------------ | +| result | bool | true/false 成功与否 | +| message | string | result=false 时错误信息 | +| data | dict | 返回数据 | + +#### data + +| 名称 | 类型 | 说明 | +| ------------ | ---------- | ------------------------------ | +| count | int | 导入的流程数 | diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/modify_constants_for_periodic_task.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/modify_constants_for_periodic_task.md index 1984aa546..f410a049f 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/modify_constants_for_periodic_task.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/modify_constants_for_periodic_task.md @@ -12,7 +12,7 @@ |---------------|------------|--------|------------------| | task_id | string | 是 | 周期任务ID | | bk_biz_id | string | 是 | 模板所属业务ID | -| constants | object | 否 | 任务全局参数,详细信息见下面说明 | +| constants | dict | 否 | 任务全局参数,详细信息见下面说明 | #### constants.KEY @@ -24,7 +24,7 @@ ### 请求参数示例 -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -37,7 +37,7 @@ ### 返回结果示例 -```python +``` { "data": { "${bk_timing}": { @@ -83,5 +83,5 @@ | desc | string | 变量说明 | | source_type | string | 变量来源, 取值范围 custom: 自定义变量,component_inputs: 从原子输入参数勾选,component_outputs:从原子输出结果中勾选 | | custom_type | string | source_type=custom 时有效,自定义变量类型, 取值范围 input: 输入框,textarea: 文本框,datetime: 日期时间,int: 整数| -| source_tag | string | source_type=component_inputs|component_outputs 时有效,变量的来源原子 | -| source_info | dict | source_type=component_inputs|component_outputs 时有效,变量的来源节点信息 | \ No newline at end of file +| source_tag | string | source_type=component_inputs/component_outputs 时有效,变量的来源原子 | +| source_info | dict | source_type=component_inputs/component_outputs 时有效,变量的来源节点信息 | diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/modify_cron_for_periodic_task.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/modify_cron_for_periodic_task.md index 84619acf7..8c8b574be 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/modify_cron_for_periodic_task.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/modify_cron_for_periodic_task.md @@ -12,7 +12,7 @@ |---------------|------------|--------|------------------| | task_id | string | 是 | 周期任务ID | | bk_biz_id | string | 是 | 模板所属业务ID | -| cron | object | 否 | 调度策略对象 | +| cron | dict | 否 | 调度策略对象 | #### cron @@ -26,7 +26,7 @@ ### 请求参数示例 -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -39,7 +39,7 @@ ### 返回结果示例 -```python +``` { "data": { "cron": "*/1 15 * * * (m/h/d/dM/MY)" diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/node_callback.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/node_callback.md new file mode 100644 index 000000000..b8e2a047f --- /dev/null +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/node_callback.md @@ -0,0 +1,49 @@ +### 功能描述 + +回调指定的节点 + +### 请求参数 + +{{ common_args_desc }} + +#### 接口参数 + +| 字段 | 参数类型 | 必须 | 参数说明 | +| ------------ | ------------ | ------ | ---------------- | +| bk_biz_id | string | 是 | 所属业务ID | +| task_id | string | 是 | 任务ID | +| node_id | string | 是 | 节点 ID | +| callback_data | dict | 否 | 回调数据 | | + +### 请求参数示例 + +``` +import requests +kwargs = { + "app_code": "app_code", + "app_secret": "app_secret", + "access_token": "access_token", + "bk_biz_id": "2", + "task_id": "10", + "node_id": "node0df0431f8f553925af01a94854bd", + "callback_data": {"data": "data"}, +} +response = requests.get("http://{stageVariables.domain}/apigw/node_callback/10/2/", kwargs) +result = response.json() +``` + +### 返回结果示例 + +``` +{ + "message": "success", + "result": true +} +``` + +### 返回结果参数说明 + +| 名称 | 类型 | 说明 | +| ------------ | ---------- | ------------------------------ | +| result | bool | true/false 成功与否 | +| message | string | result=false 时错误信息 | diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/operate_task.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/operate_task.md index 8fcde35d6..f2d695589 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/operate_task.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/operate_task.md @@ -25,7 +25,7 @@ ### 请求参数示例 -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -38,7 +38,7 @@ ### 返回结果示例 -```python +``` { "result": true, "data": {} diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/query_task_count.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/query_task_count.md index 9d0723ace..b7db45eed 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/query_task_count.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/query_task_count.md @@ -83,7 +83,7 @@ | total | int | 按照过滤条件获取的任务总数 | | groups | list | 按照过滤条件分类分类统计详情 | -#### data.groups +#### data.groups[] | 字段 | 类型 | 描述 | |-----------|----------|-----------| | code | string | 分类统计类型编码 | diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/set_periodic_task_enabled.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/set_periodic_task_enabled.md index b1afd3327..c7125860e 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/set_periodic_task_enabled.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/set_periodic_task_enabled.md @@ -16,7 +16,7 @@ ### 请求参数示例 -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -29,7 +29,7 @@ ### 返回结果示例 -```python +``` { "data": { "enabled": false diff --git a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/start_task.md b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/start_task.md index 92de38603..79007164f 100644 --- a/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/start_task.md +++ b/paas-ce/paas/esb/components/confapis/sops/apidocs/zh_hans/start_task.md @@ -15,7 +15,7 @@ ### 请求参数示例 -```python +``` { "bk_app_code": "esb_test", "bk_app_secret": "xxx", @@ -27,7 +27,7 @@ ### 返回结果示例 -```python +``` { "result": true, "data": {} diff --git a/paas-ce/paas/esb/components/confapis/sops/sops.yaml b/paas-ce/paas/esb/components/confapis/sops/sops.yaml index fa07e2444..140094eff 100644 --- a/paas-ce/paas/esb/components/confapis/sops/sops.yaml +++ b/paas-ce/paas/esb/components/confapis/sops/sops.yaml @@ -22,7 +22,7 @@ - path: /v2/sops/create_task/ name: create_task - label: 创建任务 + label: 通过流程模板新建任务 label_en: Create a task method: POST api_type: operate @@ -32,7 +32,7 @@ - path: /v2/sops/start_task/ name: start_task - label: 开始任务 + label: 开始执行任务 label_en: Start task method: POST api_type: operate @@ -52,7 +52,7 @@ - path: /v2/sops/get_task_status/ name: get_task_status - label: 查询任务或节点状态 + label: 查询任务或任务节点执行状态 label_en: Query task or node status method: GET api_type: query @@ -60,9 +60,39 @@ dest_path: /o/bk_sops/apigw/get_task_status/{task_id}/{bk_biz_id}/ dest_http_method: GET +- path: /v2/sops/get_task_detail/ + name: get_task_detail + label: 查询任务执行详情 + label_en: Query a task execution details + method: GET + api_type: query + comp_codename: generic.v2.sops.sops_component + dest_path: /o/bk_sops/apigw/get_task_detail/{task_id}/{bk_biz_id}/ + dest_http_method: GET + +- path: /v2/sops/get_task_node_detail/ + name: get_task_node_detail + label: 查询任务节点执行详情 + label_en: Query a task node execution details + method: GET + api_type: query + comp_codename: generic.v2.sops.sops_component + dest_path: /o/bk_sops/apigw/get_task_node_detail/{task_id}/{bk_biz_id}/ + dest_http_method: GET + +- path: /v2/sops/node_callback/ + name: node_callback + label: 回调任务节点 + label_en: Callback a specific node + method: POST + api_type: query + comp_codename: generic.v2.sops.sops_component + dest_path: /o/bk_sops/apigw/node_callback/{task_id}/{bk_biz_id}/ + dest_http_method: POST + - path: /v2/sops/query_task_count/ name: query_task_count - label: 查询任务分类统计 + label: 查询任务分类统计总数 label_en: Query task classification statistics method: POST api_type: operate @@ -72,7 +102,7 @@ - path: /v2/sops/get_periodic_task_list/ name: get_periodic_task_list - label: 查询周期任务列表 + label: 查询业务下的周期任务列表 label_en: Query periodic task list method: GET api_type: query @@ -82,7 +112,7 @@ - path: /v2/sops/get_periodic_task_info/ name: get_periodic_task_info - label: 查询周期任详情务 + label: 查询业务下的某个周期任务详情 label_en: Query periodic task detail method: GET api_type: query @@ -92,7 +122,7 @@ - path: /v2/sops/create_periodic_task/ name: create_periodic_task - label: 创建周期任务 + label: 通过流程模板新建周期任务 label_en: create a periodic task method: POST api_type: operate @@ -128,4 +158,15 @@ api_type: operate comp_codename: generic.v2.sops.sops_component dest_path: /o/bk_sops/apigw/modify_constants_for_periodic_task/{task_id}/{bk_biz_id}/ - dest_http_method: POST \ No newline at end of file + dest_http_method: POST + +- path: /v2/sops/import_common_template/ + name: import_common_template + label: 导入公共流程 + label_en: Import common flow + method: POST + api_type: operate + comp_codename: generic.v2.sops.sops_component + dest_path: /o/bk_sops/apigw/import_common_template/ + dest_http_method: POST + \ No newline at end of file diff --git a/paas-ce/paas/esb/components/esb_conf.py b/paas-ce/paas/esb/components/esb_conf.py index b777c5973..1d4288427 100644 --- a/paas-ce/paas/esb/components/esb_conf.py +++ b/paas-ce/paas/esb/components/esb_conf.py @@ -73,6 +73,8 @@ def _rel_path(x): '/v2/cmsi/send_mail/': '/cmsi/send_mail/', '/v2/cmsi/send_sms/': '/cmsi/send_sms/', '/v2/cmsi/send_weixin/': '/cmsi/send_weixin/', + '/v2/cmsi/get_msg_type/': '/cmsi/get_msg_type/', + '/v2/cmsi/send_msg/': '/cmsi/send_msg/', }, 'preset_channels': [ # CC v2 @@ -396,6 +398,8 @@ def _rel_path(x): 'comp_codename': 'generic.cmsi.send_voice_msg', 'comp_conf_to_db': [ ('dest_url', ''), + ('qcloud_app_id', ''), + ('qcloud_app_key', ''), ] }), ('/cmsi/send_mail/', { @@ -432,6 +436,18 @@ def _rel_path(x): ('wx_qy_agentid', ''), ] }), + ('/cmsi/get_msg_type/', { + 'comp_codename': 'generic.cmsi.get_msg_type', + 'comp_conf_to_db': [ + ('weixin', True), + ('mail', True), + ('sms', True), + ('voice', True), + ] + }), + ('/cmsi/send_msg/', { + 'comp_codename': 'generic.cmsi.send_msg' + }), # FTA ('/fta/http_relay/', { diff --git a/paas-ce/paas/esb/components/generic/templates/cmsi/apidoc/noc_notice.js b/paas-ce/paas/esb/components/generic/templates/cmsi/apidoc/noc_notice.js deleted file mode 100644 index 9e4cb2a58..000000000 --- a/paas-ce/paas/esb/components/generic/templates/cmsi/apidoc/noc_notice.js +++ /dev/null @@ -1,40 +0,0 @@ -/** -@api {post} /api/c/compapi/cmsi/noc_notice/ noc_notice -@apiName noc_notice -@apiGroup API-CMSI -@apiVersion 1.0.0 -@apiDescription 公共语音通知 -@apiParam {string} app_code 应用ID -@apiParam {string} app_secret 应用TOKEN,可以通过 蓝鲸智云开发者中心 -> 点击应用ID -> 基本信息 获取 -@apiParam {string} [bk_token] 当前用户登录态,bk_token与username必须一个有效,bk_token可以通过Cookie获取 -@apiParam {string} [username] 当前用户用户名,白名单中app可使用 - -@apiParam {string} auto_read_message 自动语音读字信息 -@apiParam {array} [user_list_information] 待通知的用户列表,自动语音通知列表,若user_list_information、receiver__username同时存在,以user_list_information为准 -@apiParam {string} [receiver__username] 待通知的用户列表,包含用户名,用户需在蓝鲸平台注册,多个以逗号分隔,若user_list_information、receiver__username同时存在,以user_list_information为准 - -@apiParam (user_list_information) {string} username 被通知人 -@apiParam (user_list_information) {string} [mobile_phone] 被通知人手机号 - -@apiParamExample {json} Request-Example: - { - "app_code": "esb_test", - "app_secret": "xxx", - "bk_token": "xxx", - "auto_read_message": "This is a test", - "user_list_information": [{ - "username": "admin", - "mobile_phone": "1234567890", - }] - } -@apiSuccessExample {json} Success-Response - HTTP/1.1 200 OK - { - "result": true, - "code": "00", - "message": "", - "data": { - "instance_id": "2662152044" - } - } - */ diff --git a/paas-ce/paas/esb/components/generic/templates/cmsi/apidocs/en/get_msg_type.md b/paas-ce/paas/esb/components/generic/templates/cmsi/apidocs/en/get_msg_type.md new file mode 100644 index 000000000..30914bfa1 --- /dev/null +++ b/paas-ce/paas/esb/components/generic/templates/cmsi/apidocs/en/get_msg_type.md @@ -0,0 +1,48 @@ +### Functional description + +Query the type of send_msg component that supports sending messages + +### Request Parameters + +{{ common_args_desc }} + +### Request Parameters Example + +```python +{ + "bk_app_code": "esb_test", + "bk_app_secret": "xxx", + "bk_token": "xxx" +} +``` + +### Return Result Example + +```python +{ + "result": true, + "code": 0, + "data": [ + { + "type": "weixin", + "label": "weixin", + "is_active": true + }, + { + "type": "mail", + "label": "mail", + "is_active": true + }, + { + "type": "sms", + "label": "sms", + "is_active": true + }, + { + "type": "voice", + "label": "voice", + "is_active": true + } + ] +} +``` diff --git a/paas-ce/paas/esb/components/generic/templates/cmsi/apidocs/en/send_msg.md b/paas-ce/paas/esb/components/generic/templates/cmsi/apidocs/en/send_msg.md new file mode 100644 index 000000000..3cd6398ad --- /dev/null +++ b/paas-ce/paas/esb/components/generic/templates/cmsi/apidocs/en/send_msg.md @@ -0,0 +1,60 @@ +### Functional description + +Universal messaging interface + +### Request Parameters + +{{ common_args_desc }} + +#### Interface Parameters + +| Field | Type | Required| Description | +|--------------------|------------|--------|-------------------| +| msg_type | string | YES | The type of information sent can be obtained through the get_msg_type interface | +| receiver__username | string | YES | Receiver, including the username, the user needs to register on the BlueKing platform, separated by commas | +| cc__username | string | No | Cc, including the user name, the user needs to register on the Blue Whale platform, multiple comma-separated, msg type is valid for mail | +| title | string | YES | Subject | +| content | string | YES | Content | +| body_format | string | No | Mail format, including 'Html', 'Text', defaults to 'Html', valid when meg type is mail | +| attachments | list | No | Mail attachment, valid when meg type is mail | +| date | string | No | Notification sending time, the default is the current time "YYYY-mm-dd HH:MM", valid when meg type is weixin | +| remark | string | No | Notify the trailing text, valid when meg type is weixin| +| wx_qy_agentid | string | No | Enterprise WeChat AgentId, valid when meg type is weixin | +| wx_qy_corpsecret | string | No | Enterprise WeChat CorpSecret, valid when meg type is weixin | +| is_content_base64 | bool | No | Notification text content is base64 encoding, default False, no encoding, if encoding, please use base64.b64encode method | + +##### attachments + +| Field | Type | Required| Description | +|--------------------|------------|--------|------------| +| filename | string | YES | file name | +| content | string | YES | File content, the content of the file is the base64 encoded string of the original file content | +| type | string | No | File type, default is the file name suffix, such as a.png file type is 'png' | +| disposition | string | No | File Content-Disposition, image file (type=image, jpg, png, jpeg) defaults to 'inline', other files default to 'attachment' | +| content_id | string | No | File Content-ID, effective when the file is an image file; default is '' | + +### Request Parameters Example + +```python +{ + "bk_app_code": "esb-test", + "bk_app_secret": "esb-test-secret", + "bk_username": "admin", + "msg_type": "mail", + "receiver__username": "admin", + "title": "xxx", + "content": "xxx" +} +``` + +### Return Result Example + +```python +{ + "result": true, + "code": 0, + "message": "OK", + "data": [], + "request_id": "sdfdfdfsdfasdasdasas" +} +``` diff --git a/paas-ce/paas/esb/components/generic/templates/cmsi/apidocs/zh_hans/get_msg_type.md b/paas-ce/paas/esb/components/generic/templates/cmsi/apidocs/zh_hans/get_msg_type.md new file mode 100644 index 000000000..27eea482c --- /dev/null +++ b/paas-ce/paas/esb/components/generic/templates/cmsi/apidocs/zh_hans/get_msg_type.md @@ -0,0 +1,48 @@ +### 功能描述 + +查询 send_msg 组件支持发送消息的类型 + +### 请求参数 + +{{ common_args_desc }} + +### 请求参数示例 + +```python +{ + "bk_app_code": "esb_test", + "bk_app_secret": "xxx", + "bk_token": "xxx" +} +``` + +### 返回结果示例 + +```python +{ + "result": true, + "code": 0, + "data": [ + { + "type": "weixin", + "label": "微信", + "is_active": true + }, + { + "type": "mail", + "label": "邮件", + "is_active": true + }, + { + "type": "sms", + "label": "短信", + "is_active": true + }, + { + "type": "voice", + "label": "语音", + "is_active": true + } + ] +} +``` diff --git a/paas-ce/paas/esb/components/generic/templates/cmsi/apidocs/zh_hans/send_msg.md b/paas-ce/paas/esb/components/generic/templates/cmsi/apidocs/zh_hans/send_msg.md new file mode 100644 index 000000000..e3595437f --- /dev/null +++ b/paas-ce/paas/esb/components/generic/templates/cmsi/apidocs/zh_hans/send_msg.md @@ -0,0 +1,62 @@ +### 功能描述 + +通用消息发送接口 + +### 请求参数 + +{{ common_args_desc }} + +#### 接口参数 + +| 字段 | 类型 |必选 | 描述 | +|--------------------|------------|--------|------------| +| msg_type | string | 是 | 发送信息的类型,可通过get_msg_type组件获取 | +| receiver__username | string | 是 | 接收者,包含用户名,用户需在蓝鲸平台注册,多个以逗号分隔 | +| title | string | 是 | 主题 | +| content | string | 是 | 内容 | +| sender | string | 否 | 发件人,msg_type 为 mail 时有效 | +| cc__username | string | 否 | 抄送人,包含用户名,用户需在蓝鲸平台注册,多个以逗号分隔,msg_type为mail时有效 | +| body_format | string | 否 | 邮件格式,包含'Html', 'Text',默认为'Html', msg_type 为 mail 时有效 | +| attachments | list | 否 | 邮件附件, msg_type 为 mail 时有效 | +| date | string | 否 | 通知发送时间,默认为当前时间 "YYYY-mm-dd HH:MM",msg_type 为 weixin 时有效 | +| remark | string | 否 | 通知尾部文字,msg_type 为 weixin 时有效| +| wx_qy_agentid | string | 否 | 企业微信AgentId,msg_type 为 weixin 时有效 | +| wx_qy_corpsecret | string | 否 | 企业微信CorpSecret,msg_type 为 weixin 时有效 | +| is_content_base64 | bool | 否 | 通知文字content是否base64编码,默认False,不编码,若编码请使用base64.b64encode方法 | + + +##### attachments + +| 字段 | 类型 |必选 | 描述 | +|--------------------|------------|--------|------------| +| filename | string | 是 | 文件名 | +| content | string | 是 | 文件内容,文件内容为原文件内容的 base64 编码字符串" | +| type | string | 否 | 文件类型,默认为文件名后缀,如 a.png 文件类型为 'png' | +| disposition | string | 否 | 文件 Content-Disposition,图片文件(type=image, jpg, png, jpeg)默认为 'inline',其他文件默认为 'attachment' | +| content_id | string | 否 | 文件 Content-ID,文件为图片文件时生效;默认为 '<文件名>' | + +### 请求参数示例 + +```python +{ + "bk_app_code": "esb-test", + "bk_app_secret": "esb-test-secret", + "bk_username": "admin", + "msg_type": "mail", + "receiver__username": "admin,yunchao", + "title": "xxx", + "content": "xxx" +} +``` + +### 返回结果示例 + +```python +{ + "result": true, + "code": 0, + "message": "OK", + "data": [], + "request_id": "sdfdfdfsdfasdasdasas" +} +``` diff --git a/paas-ce/paas/esb/components/generic/templates/cmsi/get_msg_type.py b/paas-ce/paas/esb/components/generic/templates/cmsi/get_msg_type.py new file mode 100644 index 000000000..384d14f0e --- /dev/null +++ b/paas-ce/paas/esb/components/generic/templates/cmsi/get_msg_type.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. +Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at +http://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +""" # noqa +from components.component import Component, SetupConfMixin +from common.constants import API_TYPE_Q, HTTP_METHOD +from common.base_utils import str_bool +from .toolkit import configs + + +class GetMsgType(Component, SetupConfMixin): + suggest_method = HTTP_METHOD.GET + label = u'查询消息发送类型' + label_en = 'Get message type' + + sys_name = configs.SYSTEM_NAME + api_type = API_TYPE_Q + + def handle(self): + bk_language = self.request.headers.get('Blueking-Language', 'en') + + msg_type = [] + for mt in configs.msg_type: + is_active = mt.get('is_active', str_bool(getattr(self, mt['type'], False))) + msg_type.append({ + 'type': mt['type'], + 'label': mt['label_en'] if bk_language == 'en' else mt['label'], + 'is_active': is_active, + }) + + self.response.payload = { + "result": True, + "data": msg_type, + } diff --git a/paas-ce/paas/esb/components/generic/templates/cmsi/noc_notice.py b/paas-ce/paas/esb/components/generic/templates/cmsi/noc_notice.py deleted file mode 100644 index cc5d97560..000000000 --- a/paas-ce/paas/esb/components/generic/templates/cmsi/noc_notice.py +++ /dev/null @@ -1,142 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. -Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved. -Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at -http://opensource.org/licenses/MIT -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -""" # noqa -import json - -from django import forms - -from components.component import Component, SetupConfMixin -from common.forms import BaseComponentForm, TypeCheckField, ListField -from .toolkit import configs, tools - - -class NocNotice(Component, SetupConfMixin): - """ - apiLabel 公共语音通知 - apiMethod POST - - ### 功能描述 - - 公共语音通知 - - ### 请求参数 - - {{ common_args_desc }} - - #### 接口参数 - - | 字段 | 类型 | 必选 | 描述 | - |-----------------------|------------|--------|------------| - | auto_read_message | string | 是 | 自动语音读字信息 | - | user_list_information | array | 否 | 待通知的用户列表,自动语音通知列表,若user_list_information、receiver__username同时存在,以user_list_information为准 | - | receiver__username | string | 否 | 待通知的用户列表,包含用户名,用户需在蓝鲸平台注册,多个以逗号分隔,若user_list_information、receiver__username同时存在,以user_list_information为准 | - - #### user_list_information - - | 字段 | 类型 | 必选 | 描述 | - |--------------|------------|--------|------------| - | username | string | 是 | 被通知人 | - | mobile_phone | string | 否 | 被通知人手机号 | - - ### 请求参数示例 - - ```python - { - "app_code": "esb_test", - "app_secret": "xxx", - "bk_token": "xxx", - "auto_read_message": "This is a test", - "user_list_information": [{ - "username": "admin", - "mobile_phone": "1234567890", - }] - } - ``` - - ### 返回结果示例 - - ```python - { - "result": true, - "code": "00", - "message": "", - "data": { - "instance_id": "2662152044" - } - } - ``` - """ # noqa - - sys_name = configs.SYSTEM_NAME - host = configs.host - contact_way = 'phone' - dest_url = '' - - class Form(BaseComponentForm): - auto_read_message = forms.CharField(label=u'自动语音读字信息', required=True) - user_list_information = TypeCheckField(label=u'用户列表', promise_type=list, required=False) - receiver__username = ListField(label=u'蓝鲸用户列表', required=False) - - def clean(self): - data = self.cleaned_data - user_list_information = [ - NocNotice.UserListInfoForm(user_info).get_cleaned_data_or_error() - for user_info in data['user_list_information'] - if user_info - ] - if not (data.get('receiver__username') or user_list_information): - raise forms.ValidationError(u'参数[user_list_information、receiver__username]不能同时为空') - data['user_list_information'] = user_list_information - if user_list_information: - data['receiver__username'] = None - return data - - class UserListInfoForm(BaseComponentForm): - username = forms.CharField(label=u'被通知人', required=True) - mobile_phone = forms.CharField(label=u'被通知人手机号', required=False) - - def clean(self): - data = self.cleaned_data - if data['mobile_phone'] and not data['mobile_phone'].isdigit(): - raise forms.ValidationError(u'被通知人手机号[mobile_phone]必须是一个数字。') - return data - - def handle(self): - data = self.request.kwargs - # 将 receiver__username 中的用户名,转换为接口需要的 user_list_information 信息 - if data['receiver__username']: - user_data = tools.get_user_contact_with_username( - username_list=data['receiver__username'], - contact_way=self.contact_way, - ) - data['user_list_information'] = [ - { - 'username': username, - 'mobile_phone': contact_info, - } - for username, contact_info in user_data['user_contact_info'].iteritems() - ] - data['_extra_user_error_msg'] = user_data['_extra_user_error_msg'] - - # TODO: can be updated - if self.dest_url: - result = self.outgoing.http_client.request_by_url( - 'POST', - self.dest_url, - data=json.dumps(data) - ) - - if result['result'] and data.get('_extra_user_error_msg'): - result = { - 'result': False, - 'data': result.get('data'), - 'message': u'部分用户语音发送失败。%s' % data['_extra_user_error_msg'], - } - self.response.payload = result - else: - self.response.payload = {'result': False, 'message': u'未完成接口,需要组件负责人进行完善'} diff --git a/paas-ce/paas/esb/components/generic/templates/cmsi/send_mail.py b/paas-ce/paas/esb/components/generic/templates/cmsi/send_mail.py index c29586e9b..ee9bd00a5 100644 --- a/paas-ce/paas/esb/components/generic/templates/cmsi/send_mail.py +++ b/paas-ce/paas/esb/components/generic/templates/cmsi/send_mail.py @@ -12,7 +12,7 @@ from django import forms from components.component import Component, SetupConfMixin -from common.forms import BaseComponentForm, ListField, DefaultBooleanField +from common.forms import BaseComponentForm, ListField, DefaultBooleanField, TypeCheckField from common.base_utils import str_bool from common.constants import API_TYPE_OP from .toolkit import configs, tools, send_mail_with_smtp @@ -44,7 +44,17 @@ class SendMail(Component, SetupConfMixin): | cc__username | string | {{ _("否") }} | {{ _("抄送人,包含用户名,用户需在蓝鲸平台注册,多个以逗号分隔,若cc、cc__username同时存在,以cc为准") }} | | body_format | string | {{ _("否") }} | {{ _("邮件格式,包含'Html', 'Text',默认为'Html'") }} | | is_content_base64 | bool | {{ _("否") }} | {{ _("邮件内容是否base64编码,默认False,不编码,请使用base64.b64encode方法编码") }} | + | attachments | bool | {{ _("否") }} | {{ _("邮件附件") }} | + ##### attachments + + | {{ _("字段") }} | {{ _("类型") }} | {{ _("必选") }} | {{ _("描述") }} | + |--------------------|------------|--------|------------| + | filename | string | {{ _("是") }} | {{ _("文件名") }} | + | content | string | {{ _("是") }} | {{ _("文件内容,文件内容为原文件内容的 base64 编码字符串") }} | + | type | string | {{ _("否") }} | {{ _("文件类型,默认为文件名后缀,如 a.png 文件类型为 'png'") }} | + | disposition | string | {{ _("否") }} | {{ _("文件 Content-Disposition,图片文件(type=image, jpg, png, jpeg)默认为 'inline',其他文件默认为 'attachment'") }} | + | content_id | string | {{ _("否") }} | {{ _("文件 Content-ID,文件为图片文件时生效;默认为 '<文件名>'") }} | ### {{ _("请求参数示例") }} @@ -88,6 +98,7 @@ class Form(BaseComponentForm): is_content_base64 = DefaultBooleanField( label='content is encoded by base64 or not', default=False, required=False) body_format = forms.CharField(label='email format', required=False) + attachments = TypeCheckField(label='attachments', promise_type=list, required=False) def clean(self): data = self.cleaned_data @@ -103,8 +114,24 @@ def clean(self): data['content'] = base64.b64decode(data['content']) except Exception: pass + if data['attachments']: + data['attachments'] = [ + SendMail.AttachmentForm(attachment).get_cleaned_data_or_error() + for attachment in data['attachments'] + ] return data + class AttachmentForm(BaseComponentForm): + filename = forms.CharField(label='filename', required=True) + content = forms.CharField(label='content', required=True) + type = forms.CharField(label='type', required=False) + disposition = forms.CharField(label='disposition', required=False) + content_id = forms.CharField(label='content_id', required=False) + + def clean(self): + self.cleaned_data['content'] = base64.b64decode(self.cleaned_data['content']) + return self.cleaned_data + def handle(self): # 默认支持通过 SMTP 服务器或第三方接口发送邮件, # 为实现邮件发送,需完善组件配置,有以下两种方式: diff --git a/paas-ce/paas/esb/components/generic/templates/cmsi/send_msg.py b/paas-ce/paas/esb/components/generic/templates/cmsi/send_msg.py new file mode 100644 index 000000000..210d08a58 --- /dev/null +++ b/paas-ce/paas/esb/components/generic/templates/cmsi/send_msg.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. +Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at +http://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +""" # noqa +from django import forms + +from components.component import Component, SetupConfMixin +from esb.channel import get_channel_manager +from common.forms import BaseComponentForm, ListField, DefaultBooleanField, TypeCheckField +from common.constants import API_TYPE_OP, HTTP_METHOD +from .toolkit import configs + + +class SendMsg(Component, SetupConfMixin): + suggest_method = HTTP_METHOD.POST + label = u'通用消息发送' + label_en = 'Send message' + + sys_name = configs.SYSTEM_NAME + api_type = API_TYPE_OP + msg_type_map = configs.msg_type_map + + class Form(BaseComponentForm): + msg_type = forms.CharField(label='msg type', required=True) + receiver__username = ListField(label='recipients', required=True) + sender = forms.CharField(label='mail sender', required=False) + cc__username = ListField(label='CC', required=False) + title = forms.CharField(label='subject', required=True) + content = forms.CharField(label='content', required=True) + body_format = forms.CharField(label='email format', required=False) + attachments = TypeCheckField(label='attachments', promise_type=list, required=False) + date = forms.CharField(label='notification sending time', required=False) + remark = forms.CharField(label='notification tail text', required=False) + wx_qy_agentid = forms.CharField(label='enterprise wechat agentid', required=False) + wx_qy_corpsecret = forms.CharField(label='enterprise wechat corpsecret', required=False) + is_content_base64 = DefaultBooleanField( + label='content is encoded by base64 or not', default=False, required=False) + + def clean(self): + data = self.cleaned_data + if data['msg_type'] == "voice": + data['auto_read_message'] = data['content'] + + if data['msg_type'] == "weixin": + data['data'] = { + 'heading': data['title'], + 'message': data['content'], + 'date': data['date'], + 'remark': data['remark'], + 'is_message_base64': data['is_content_base64'] + } + + return data + + def handle(self): + data = self.form_data + msg_type = data.pop('msg_type') + + channel_manager = get_channel_manager() + + if msg_type not in configs.msg_type_map: + self.response.payload = { + 'result': False, + 'message': 'Unsupported type of msg type' + } + return + + path = '/cmsi/%s/' % self.msg_type_map[msg_type] + channel_conf = channel_manager.get_channel_by_path(path, 'POST') + comp_obj = self.prepare_other('generic.cmsi.%s' % self.msg_type_map[msg_type], kwargs=data) + comp_obj.setup_conf(channel_conf['comp_conf']) + self.response.payload = comp_obj.invoke() diff --git a/paas-ce/paas/esb/components/generic/templates/cmsi/send_sms.py b/paas-ce/paas/esb/components/generic/templates/cmsi/send_sms.py index 7acc8bb32..f07f73c5a 100644 --- a/paas-ce/paas/esb/components/generic/templates/cmsi/send_sms.py +++ b/paas-ce/paas/esb/components/generic/templates/cmsi/send_sms.py @@ -95,9 +95,6 @@ def handle(self): self.qcloud_app_id = getattr(self, 'qcloud_app_id', '') or getattr(configs, 'qcloud_app_id', '') self.qcloud_app_key = getattr(self, 'qcloud_app_key', '') or getattr(configs, 'qcloud_app_key', '') - # 第三方接口地址配置 - self.dest_url = getattr(self, 'dest_url', '') or getattr(configs, 'send_sms_dest_url', '') - data = self.request.kwargs if data['receiver']: tools.validate_receiver(data['receiver'], contact_way=self.contact_way) diff --git a/paas-ce/paas/esb/components/generic/templates/cmsi/send_voice_msg.py b/paas-ce/paas/esb/components/generic/templates/cmsi/send_voice_msg.py index 99895fa0f..0e6918098 100644 --- a/paas-ce/paas/esb/components/generic/templates/cmsi/send_voice_msg.py +++ b/paas-ce/paas/esb/components/generic/templates/cmsi/send_voice_msg.py @@ -7,7 +7,6 @@ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa import json - from django import forms from components.component import Component, SetupConfMixin @@ -110,7 +109,11 @@ def clean(self): return data def handle(self): - data = self.request.kwargs + # QCloud 语音配置 + self.qcloud_app_id = getattr(self, 'qcloud_app_id', '') or getattr(configs, 'qcloud_app_id', '') + self.qcloud_app_key = getattr(self, 'qcloud_app_key', '') or getattr(configs, 'qcloud_app_key', '') + + data = self.form_data # 将 receiver__username 中的用户名,转换为接口需要的 user_list_information 信息 if data['receiver__username']: user_data = tools.get_user_contact_with_username( @@ -141,6 +144,36 @@ def handle(self): 'message': u'Some users failed to send voice. %s' % data['_extra_user_error_msg'], } self.response.payload = result + elif self.qcloud_app_id and self.qcloud_app_key: + params = { + 'user_list_information': data['user_list_information'], + 'auto_read_message': data['auto_read_message'], + 'qcloud_app_id': self.qcloud_app_id, + 'qcloud_app_key': self.qcloud_app_key + } + ret = self.invoke_other('generic.qcloud_voice.send_voice_msg', kwargs=params) + + if not ret['failed'] and data.get('_extra_user_error_msg'): + result = { + 'result': False, + 'data': ret, + 'message': u'Some users failed to send voice. %s' % data['_extra_user_error_msg'], + } + elif ret['failed']: + result = { + 'result': False, + 'data': ret, + 'message': 'Some users failed to send voice. %s' % ",".join( + map(lambda x: x['username'], ret['failed']) + ) + } + else: + result = { + 'result': True, + 'data': ret, + 'message': 'OK' + } + self.response.payload = result else: self.response.payload = { 'result': False, diff --git a/paas-ce/paas/esb/components/generic/templates/cmsi/send_weixin.py b/paas-ce/paas/esb/components/generic/templates/cmsi/send_weixin.py index fc0b69749..1c0a87be3 100644 --- a/paas-ce/paas/esb/components/generic/templates/cmsi/send_weixin.py +++ b/paas-ce/paas/esb/components/generic/templates/cmsi/send_weixin.py @@ -37,6 +37,8 @@ class SendWeixin(Component, SetupConfMixin): | receiver | string | {{ _("否") }} | {{ _("微信接收者,包含绑定在指定公众号上的微信用户的 openid 或 企业号上的微信用户的用户ID,多个以逗号分隔") }} | | receiver__username | string | {{ _("否") }} | {{ _("微信接收者,包含用户名,用户需在蓝鲸平台注册,多个以逗号分隔,若receiver、receiver__username同时存在,以receiver为准") }} | | data | dict | {{ _("是") }} | {{ _("消息内容") }} | + | wx_qy_agentid | string | {{ _("否") }} | agentid of WeChat app | + | wx_qy_corpsecret | string | {{ _("否") }} | secret of WeChat app | #### {{ _("data 参数包含内容") }} @@ -88,7 +90,7 @@ class Form(BaseComponentForm): def clean(self): data = self.cleaned_data - if not(data['receiver'] or data['receiver__username']): + if not (data['receiver'] or data['receiver__username']): raise forms.ValidationError( 'WeChat receiver [receiver, receiver__username] shall not be empty at the same time') if data['receiver']: @@ -153,16 +155,23 @@ def get_qy_msg_content(self, data): def handle(self): # 微信类型,包括微信公众号"mp",微信企业号"qy" self.wx_type = getattr(self, 'wx_type', '') or getattr(configs, 'wx_type', '') + # 微信公众号配置 # 组件会根据 wx_app_id & wx_secret 申请微信的 access_token, # 业务如希望集中管理 access_token,可优化 components/apis/weixin_mp/get_token.py 中 access_token 获取逻辑 self.wx_app_id = getattr(self, 'wx_app_id', '') or getattr(configs, 'wx_app_id', '') self.wx_secret = getattr(self, 'wx_secret', '') or getattr(configs, 'wx_secret', '') self.wx_template_id = getattr(self, 'wx_template_id', '') or getattr(configs, 'wx_template_id', '') + # 微信企业号配置 + # 支持蓝鲸应用传递企业微信应用账号信息 wx_qy_corpsecret + wx_qy_agentid ,以实现通过不同企业微信应用发送消息 self.wx_qy_corpid = getattr(self, 'wx_qy_corpid', '') or getattr(configs, 'wx_qy_corpid', '') - self.wx_qy_corpsecret = getattr(self, 'wx_qy_corpsecret', '') or getattr(configs, 'wx_qy_corpsecret', '') - self.wx_qy_agentid = getattr(self, 'wx_qy_agentid', '') or getattr(configs, 'wx_qy_agentid', '') + self.wx_qy_corpsecret = self.request.kwargs.get('wx_qy_corpsecret') \ + or getattr(self, 'wx_qy_corpsecret', '') \ + or getattr(configs, 'wx_qy_corpsecret', '') + self.wx_qy_agentid = self.request.kwargs.get('wx_qy_agentid') \ + or getattr(self, 'wx_qy_agentid', '') \ + or getattr(configs, 'wx_qy_agentid', '') data = self.form_data # 根据蓝鲸平台用户数据,将用户名转换为微信用户ID diff --git a/paas-ce/paas/esb/components/generic/templates/cmsi/toolkit/configs.py b/paas-ce/paas/esb/components/generic/templates/cmsi/toolkit/configs.py index f9d53d59b..464ad55f3 100644 --- a/paas-ce/paas/esb/components/generic/templates/cmsi/toolkit/configs.py +++ b/paas-ce/paas/esb/components/generic/templates/cmsi/toolkit/configs.py @@ -28,7 +28,7 @@ # 通过第三方接口发送邮件的配置 -dest_url = '' # 第三方接口完整路径 +dest_url = '' # 邮件第三方接口完整路径 # send_weixin 组件微信消息类型配置 wx_type = 'qy' @@ -46,3 +46,34 @@ # 发送短信腾讯云配置 sdkappid 对应的 appkey,需要业务方高度保密 qcloud_app_id = '' qcloud_app_key = '' + +# cmsi支持的信息发送类型 +msg_type = [ + { + "type": "weixin", + "label": u"微信", + "label_en": "weixin" + }, + { + "type": "mail", + "label": u"邮件", + "label_en": "mail" + }, + { + "type": "sms", + "label": u"短信", + "label_en": "sms" + }, + { + "type": "voice", + "label": u"语音", + "label_en": "voice" + } +] + +msg_type_map = { + "weixin": "send_weixin", + "mail": "send_mail", + "sms": "send_sms", + "voice": "send_voice_msg" +} diff --git a/paas-ce/paas/esb/components/generic/templates/cmsi/toolkit/send_mail_with_smtp.py b/paas-ce/paas/esb/components/generic/templates/cmsi/toolkit/send_mail_with_smtp.py index 3ad6009db..fd72c88d8 100644 --- a/paas-ce/paas/esb/components/generic/templates/cmsi/toolkit/send_mail_with_smtp.py +++ b/paas-ce/paas/esb/components/generic/templates/cmsi/toolkit/send_mail_with_smtp.py @@ -36,7 +36,10 @@ def send_mail(self, kwargs): mail_sender = kwargs['sender'] all_receiver = kwargs['receiver'] + kwargs['cc'] - msg = MIMEMultipart() + if kwargs.get('mime_subtype'): + msg = MIMEMultipart(kwargs['mime_subtype']) + else: + msg = MIMEMultipart() msg['Subject'] = Header(smart_str(kwargs['title']), 'utf-8') msg['From'] = mail_sender msg['To'] = COMMASPACE.join(kwargs['receiver']) @@ -45,6 +48,9 @@ def send_mail(self, kwargs): # 添加邮件内容 self.add_content_to_msg(msg, kwargs['content'], kwargs.get('body_format')) + # 加载附件 + self.add_attachment_to_msg(msg, kwargs.get('attachments')) + try: smtp = self.get_smtp_client() smtp.sendmail(mail_sender, all_receiver, msg.as_string()) @@ -61,7 +67,7 @@ def add_content_to_msg(self, mail_msg, content, body_format): msgtxt = MIMEText(smart_str(content), body_format, 'utf-8') mail_msg.attach(msgtxt) - def add_attachment_to_msg(self, mail_msg, attachment): + def add_attachment_to_msg(self, mail_msg, attachments): """ :param attachment: [ @@ -72,22 +78,27 @@ def add_attachment_to_msg(self, mail_msg, attachment): } ] """ - for file_info in attachment: - file_name = file_info['file_name'] - file_content = file_info['file_content'] - file_type = file_name.split('.')['-1'] or file_info.get('file_type', 'attachment') + for f_info in attachments or []: + _filename = f_info.get('filename', '') + _content = f_info.get('content', '') + _type = f_info.get('type') or _filename.split('.')[-1] or 'attachment' + _disposition = f_info.get('disposition', '') # 添加二进制附件 - if file_type in ['image', 'jpg', 'png', 'jpeg']: - att = MIMEImage(file_content) - att.add_header('Content-ID', '<%s>' % file_name) - mail_msg.attach(att) + if _type in ['image', 'jpg', 'png', 'jpeg']: + content_id = f_info.get('content_id') or '<%s>' % _filename + _disposition = _disposition or 'inline' + msgImage = MIMEImage(_content, name=_filename) + msgImage.add_header('Content-ID', content_id) + msgImage.add_header('Content-Disposition', _disposition, filename=_filename) + mail_msg.attach(msgImage) else: - ctype, encoding = mimetypes.guess_type(file_name) + _disposition = _disposition or 'attachment' + ctype, encoding = mimetypes.guess_type(_filename) if ctype is None or encoding is not None: ctype = 'application/octet-stream' maintype, subtype = ctype.split('/', 1) - att = MIMEImage(file_content, _subtype=subtype) - att.add_header('Content-Disposition', 'attachment', filename=file_name) + att = MIMEImage(_content, _subtype=subtype) + att.add_header('Content-Disposition', _disposition, filename=_filename) mail_msg.attach(att) def get_smtp_client(self): diff --git a/paas-ce/paas/esb/components/generic/templates/cmsi/toolkit/tools.py b/paas-ce/paas/esb/components/generic/templates/cmsi/toolkit/tools.py index f455e2565..6e3d71163 100644 --- a/paas-ce/paas/esb/components/generic/templates/cmsi/toolkit/tools.py +++ b/paas-ce/paas/esb/components/generic/templates/cmsi/toolkit/tools.py @@ -46,7 +46,7 @@ def validate_receiver(receiver, contact_way='phone'): else: error_contact_user.append(user_contact) if error_contact_user: - raise CommonAPIError(u'用户消息发送失败。以下用户联系方式格式错误:%s,请进行检查' % ','.join(error_contact_user)) + raise CommonAPIError('User message failed to send. The following users contact format are incorrect: %s, please check' % ','.join(error_contact_user)) # noqa return valid_receiver @@ -65,7 +65,7 @@ def get_receiver_with_username(receiver__username=None, # noqa from components.bk.apis.bk_login.get_batch_user import GetBatchUser user_result = GetBatchUser().invoke(kwargs={'username_list': username_list}) if not user_result['result']: - raise CommonAPIError(u'根据用户名批量获取用户联系方式失败,%s' % user_result['message']) + raise CommonAPIError(u'Failed to get users contact information based on username, %s' % user_result['message']) result = {} not_exist_user = [] @@ -99,13 +99,14 @@ def get_receiver_with_username(receiver__username=None, # noqa _extra_user_error_msg = [] if not_exist_user: - _extra_user_error_msg.append(u'以下用户不是蓝鲸用户:%s' % ','.join(not_exist_user)) + _extra_user_error_msg.append(u'The following users are not blueking users: %s' % ','.join(not_exist_user)) if error_contact_user: - _extra_user_error_msg.append(u'以下用户联系方式格式错误:%s' % ','.join(error_contact_user)) + _extra_user_error_msg.append(u'The following users contact format are incorrect: %s' + % ','.join(error_contact_user)) result['_extra_user_error_msg'] = ';'.join(_extra_user_error_msg) if receiver__username and not result.get('receiver'): - raise CommonAPIError(u'全部用户消息发送失败。%s' % result['_extra_user_error_msg']) + raise CommonAPIError(u'All users message failed to be sent. %s' % result['_extra_user_error_msg']) return result @@ -114,7 +115,7 @@ def get_user_contact_with_username(username_list=None, contact_way='phone'): from components.bk.apis.bk_login.get_batch_user import GetBatchUser user_result = GetBatchUser().invoke(kwargs={'username_list': username_list}) if not user_result['result']: - raise CommonAPIError(u'根据用户名批量获取用户联系方式失败,%s' % user_result['message']) + raise CommonAPIError(u'Failed to get users contact information based on username, %s' % user_result['message']) user_contact_info = {} not_exist_user = [] @@ -133,13 +134,14 @@ def get_user_contact_with_username(username_list=None, contact_way='phone'): _extra_user_error_msg = [] if not_exist_user: - _extra_user_error_msg.append(u'以下用户不是蓝鲸用户:%s' % ','.join(not_exist_user)) + _extra_user_error_msg.append(u'The following users are not blueking users: %s' % ','.join(not_exist_user)) if error_contact_user: - _extra_user_error_msg.append(u'以下用户联系方式格式错误:%s' % ','.join(error_contact_user)) + _extra_user_error_msg.append(u'The following users contact format are incorrect: %s' + % ','.join(error_contact_user)) _extra_user_error_msg = ';'.join(_extra_user_error_msg) if not user_contact_info: - raise CommonAPIError(u'全部用户联系方式获取失败。%s' % _extra_user_error_msg) + raise CommonAPIError(u'All users contact information failed to get, %s' % _extra_user_error_msg) return { 'user_contact_info': user_contact_info, diff --git a/paas-ce/paas/esb/components/generic/templates/heartbeat/detect.py b/paas-ce/paas/esb/components/generic/templates/heartbeat/detect.py index d9f228568..db4c92c3a 100644 --- a/paas-ce/paas/esb/components/generic/templates/heartbeat/detect.py +++ b/paas-ce/paas/esb/components/generic/templates/heartbeat/detect.py @@ -22,8 +22,8 @@ class Detect(Component): sys_name = configs.SYSTEM_NAME class Form(BaseComponentForm): - timestamp = forms.IntegerField(label=u'心跳时间', required=True) - sleep_time = forms.IntegerField(label=u'Sleep时间', required=False) + timestamp = forms.IntegerField(label='timestamp', required=True) + sleep_time = forms.IntegerField(label='sleep time', required=False) def handle(self): if self.form_data.get('sleep_time'): diff --git a/paas-ce/paas/esb/components/generic/templates/qcloud_sms/send_multi_sms.py b/paas-ce/paas/esb/components/generic/templates/qcloud_sms/send_multi_sms.py index 7db2526d7..5669f5d12 100644 --- a/paas-ce/paas/esb/components/generic/templates/qcloud_sms/send_multi_sms.py +++ b/paas-ce/paas/esb/components/generic/templates/qcloud_sms/send_multi_sms.py @@ -21,14 +21,14 @@ class SendMultiSms(Component, SetupConfMixin): api_type = API_TYPE_OP class Form(BaseComponentForm): - sdk_app_id = forms.CharField(label=u'腾讯云sdkappid', required=True) - app_key = forms.CharField(label=u'腾讯云appkey', required=True) - sms_type = forms.IntegerField(label=u'短信类型', required=False) - nation_code = forms.CharField(label=u'国家码', required=False) - phone_numbers = ListField(label=u'不带国家码的手机号', required=True) - content = forms.CharField(label=u'消息内容', required=True) - extend = forms.CharField(label=u'通道扩展码', required=False) - ext = forms.CharField(label=u'服务端原样返回的参数', required=False) + sdk_app_id = forms.CharField(label='tencent cloud sdkappid', required=True) + app_key = forms.CharField(label='tencent cloud appkey', required=True) + sms_type = forms.IntegerField(label='sms type', required=False) + nation_code = forms.CharField(label='nation code', required=False) + phone_numbers = ListField(label='phone numbers', required=True) + content = forms.CharField(label='content', required=True) + extend = forms.CharField(label='extend', required=False) + ext = forms.CharField(label='ext', required=False) def clean(self): data = self.cleaned_data diff --git a/paas-ce/paas/esb/components/generic/templates/qcloud_sms/send_multi_sms_with_tpl.py b/paas-ce/paas/esb/components/generic/templates/qcloud_sms/send_multi_sms_with_tpl.py index c4e5dc206..e82cb443d 100644 --- a/paas-ce/paas/esb/components/generic/templates/qcloud_sms/send_multi_sms_with_tpl.py +++ b/paas-ce/paas/esb/components/generic/templates/qcloud_sms/send_multi_sms_with_tpl.py @@ -21,15 +21,15 @@ class SendMultiSmsWithTpl(Component, SetupConfMixin): api_type = API_TYPE_OP class Form(BaseComponentForm): - sdk_app_id = forms.CharField(label=u'腾讯云sdkappid', required=True) - app_key = forms.CharField(label=u'腾讯云appkey', required=True) - sign = forms.CharField(label=u'短信签名', required=False) - tpl_id = forms.IntegerField(label=u'短信模版ID', required=True) - params = TypeCheckField(label=u'模版参数', promise_type=list, required=False) - nation_code = forms.CharField(label=u'国家码', required=False) - phone_numbers = ListField(label=u'不带国家码的手机号', required=True) - extend = forms.CharField(label=u'通道扩展码', required=False) - ext = forms.CharField(label=u'服务端原样返回的参数', required=False) + sdk_app_id = forms.CharField(label='tencent cloud sdkappid', required=True) + app_key = forms.CharField(label='tencent cloud appkey', required=True) + sign = forms.CharField(label='sms signature', required=False) + tpl_id = forms.IntegerField(label='template id', required=True) + params = TypeCheckField(label='template params', promise_type=list, required=False) + nation_code = forms.CharField(label='nation code', required=False) + phone_numbers = ListField(label='phone numbers', required=True) + extend = forms.CharField(label='extend', required=False) + ext = forms.CharField(label='ext', required=False) def clean(self): data = self.cleaned_data diff --git a/paas-ce/paas/esb/components/generic/templates/qcloud_sms/send_sms.py b/paas-ce/paas/esb/components/generic/templates/qcloud_sms/send_sms.py index 452d6bb3f..6bf2793c6 100644 --- a/paas-ce/paas/esb/components/generic/templates/qcloud_sms/send_sms.py +++ b/paas-ce/paas/esb/components/generic/templates/qcloud_sms/send_sms.py @@ -21,14 +21,14 @@ class SendSms(Component, SetupConfMixin): api_type = API_TYPE_OP class Form(BaseComponentForm): - sdk_app_id = forms.CharField(label=u'腾讯云sdkappid', required=True) - app_key = forms.CharField(label=u'腾讯云appkey', required=True) - sms_type = forms.IntegerField(label=u'短信类型', required=False) - nation_code = forms.CharField(label=u'国家码', required=False) - phone_number = forms.CharField(label=u'不带国家码的手机号', required=True) - content = forms.CharField(label=u'消息内容', required=True) - extend = forms.CharField(label=u'通道扩展码', required=False) - ext = forms.CharField(label=u'服务端原样返回的参数', required=False) + sdk_app_id = forms.CharField(label='tencent cloud sdkappid', required=True) + app_key = forms.CharField(label='tencent cloud appkey', required=True) + sms_type = forms.IntegerField(label='sms type', required=False) + nation_code = forms.CharField(label='nation code', required=False) + phone_number = forms.CharField(label='phone number', required=True) + content = forms.CharField(label='content', required=True) + extend = forms.CharField(label='extend', required=False) + ext = forms.CharField(label='ext', required=False) def clean(self): data = self.cleaned_data diff --git a/paas-ce/paas/esb/components/generic/templates/qcloud_sms/send_sms_with_tpl.py b/paas-ce/paas/esb/components/generic/templates/qcloud_sms/send_sms_with_tpl.py index 09d651ebd..16db4c990 100644 --- a/paas-ce/paas/esb/components/generic/templates/qcloud_sms/send_sms_with_tpl.py +++ b/paas-ce/paas/esb/components/generic/templates/qcloud_sms/send_sms_with_tpl.py @@ -21,15 +21,15 @@ class SendSmsWithTpl(Component, SetupConfMixin): api_type = API_TYPE_OP class Form(BaseComponentForm): - sdk_app_id = forms.CharField(label=u'腾讯云sdkappid', required=True) - app_key = forms.CharField(label=u'腾讯云appkey', required=True) - sign = forms.CharField(label=u'短信签名', required=False) - tpl_id = forms.IntegerField(label=u'短信模版ID', required=True) - params = TypeCheckField(label=u'模版参数', promise_type=list, required=False) - nation_code = forms.CharField(label=u'国家码', required=False) - phone_number = forms.CharField(label=u'不带国家码的手机号', required=True) - extend = forms.CharField(label=u'通道扩展码', required=False) - ext = forms.CharField(label=u'服务端原样返回的参数', required=False) + sdk_app_id = forms.CharField(label='tencent cloud sdkappid', required=True) + app_key = forms.CharField(label='tencent cloud appkey', required=True) + sign = forms.CharField(label='sms signature', required=False) + tpl_id = forms.IntegerField(label='template id', required=True) + params = TypeCheckField(label='template params', promise_type=list, required=False) + nation_code = forms.CharField(label='nation code', required=False) + phone_number = forms.CharField(label=u'phone number', required=True) + extend = forms.CharField(label='extend', required=False) + ext = forms.CharField(label='ext', required=False) def clean(self): data = self.cleaned_data diff --git a/paas-ce/paas/esb/components/generic/templates/qcloud_sms/toolkit/tools.py b/paas-ce/paas/esb/components/generic/templates/qcloud_sms/toolkit/tools.py index 08c8f0814..d364ff73a 100644 --- a/paas-ce/paas/esb/components/generic/templates/qcloud_sms/toolkit/tools.py +++ b/paas-ce/paas/esb/components/generic/templates/qcloud_sms/toolkit/tools.py @@ -33,7 +33,11 @@ def calculate_sig(self, app_key, rnd, cur_time, phone_numbers): def post(self, path, data): result = self.http_client.post(configs.host, path, data=json.dumps(data)) if result.get('ErrorCode'): - return {'result': False, 'message': result.get('ErrorInfo', u'出现未知错误'), 'data': result} + return { + 'result': False, + 'message': result.get('ErrorInfo', u'An unknown error has occurred'), + 'data': result + } if result['result'] == 0: return { 'result': True, diff --git a/paas-ce/paas/esb/components/generic/templates/qcloud_voice/__init__.py b/paas-ce/paas/esb/components/generic/templates/qcloud_voice/__init__.py new file mode 100644 index 000000000..f5459e554 --- /dev/null +++ b/paas-ce/paas/esb/components/generic/templates/qcloud_voice/__init__.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. +Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at +http://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +""" # noqa diff --git a/paas-ce/paas/esb/components/generic/templates/qcloud_voice/send_voice_msg.py b/paas-ce/paas/esb/components/generic/templates/qcloud_voice/send_voice_msg.py new file mode 100644 index 000000000..92bca6377 --- /dev/null +++ b/paas-ce/paas/esb/components/generic/templates/qcloud_voice/send_voice_msg.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. +Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at +http://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +""" # noqa +from django import forms + +from components.component import Component, SetupConfMixin +from common.forms import BaseComponentForm, TypeCheckField +from common.constants import API_TYPE_OP +from .toolkit import tools, configs + + +class SendVoiceMsg(Component, SetupConfMixin): + """""" + + sys_name = configs.SYSTEM_NAME + api_type = API_TYPE_OP + + class Form(BaseComponentForm): + qcloud_app_id = forms.CharField(label='qcloud app id', required=True) + qcloud_app_key = forms.CharField(label='qcloud app key', required=True) + auto_read_message = forms.CharField(label='auto voice reading info', required=True) + user_list_information = TypeCheckField(label='user list', promise_type=list, required=True) + ext = forms.CharField(label='ext', required=False) + + def kwargs_generator(self, data): + for user in data['user_list_information']: + yield { + "user": user, + "promptfile": data['auto_read_message'], + "playtimes": configs.voice_playtimes, + "prompttype": configs.voice_prompttype, + "tel": { + "mobile": user['mobile_phone'], + "nationcode": configs.default_nation_code + }, + "ext": data['ext'] + } + + def clean(self): + data = self.cleaned_data + return { + "kwargs_generator": self.kwargs_generator(data), + "qcloud_app_id": data["qcloud_app_id"], + "qcloud_app_key": data["qcloud_app_key"] + } + + def handle(self): + data = self.request.kwargs['kwargs_generator'] + client = tools.QCloudVoiceClient(self.outgoing.http_client) + result = { + "successed": [], + "failed": [] + } + for kwargs in data: + rnd = client.get_random() + cur_time = client.get_cur_time() + kwargs['time'] = cur_time + kwargs['sig'] = client.generate_sig( + self.request.kwargs['qcloud_app_key'], + kwargs['tel']['mobile'], + rnd, + cur_time + ) + + user = kwargs.pop('user') + ret = client.post( + '/v5/tlsvoicesvr/sendvoiceprompt?sdkappid=%s&random=%s' % (self.request.kwargs['qcloud_app_id'], rnd), + data=kwargs + ) + user.update(ret) + result['successed'].append(user) if ret['result'] == 0 else result['failed'].append(user) + + self.response.payload = result diff --git a/paas-ce/paas/esb/components/generic/templates/qcloud_voice/toolkit/__init__.py b/paas-ce/paas/esb/components/generic/templates/qcloud_voice/toolkit/__init__.py new file mode 100644 index 000000000..f5459e554 --- /dev/null +++ b/paas-ce/paas/esb/components/generic/templates/qcloud_voice/toolkit/__init__.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. +Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at +http://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +""" # noqa diff --git a/paas-ce/paas/esb/components/generic/templates/qcloud_voice/toolkit/configs.py b/paas-ce/paas/esb/components/generic/templates/qcloud_voice/toolkit/configs.py new file mode 100644 index 000000000..f183d8b2d --- /dev/null +++ b/paas-ce/paas/esb/components/generic/templates/qcloud_voice/toolkit/configs.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. +Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at +http://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +""" # noqa +from esb.utils import SmartHost + + +SYSTEM_NAME = 'QCLOUD_VOICE' + +host = SmartHost( + host_prod='https://cloud.tim.qq.com' +) + +default_nation_code = '86' +voice_playtimes = 3 +voice_prompttype = 2 diff --git a/paas-ce/paas/esb/components/generic/templates/qcloud_voice/toolkit/tools.py b/paas-ce/paas/esb/components/generic/templates/qcloud_voice/toolkit/tools.py new file mode 100644 index 000000000..de0d11034 --- /dev/null +++ b/paas-ce/paas/esb/components/generic/templates/qcloud_voice/toolkit/tools.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. +Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at +http://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +""" # noqa +import json +import random +import time +import hashlib + +from . import configs + + +class QCloudVoiceClient(object): + + def __init__(self, http_client): + self.http_client = http_client + + def get_random(self): + return random.randint(10000, 99999) + + def get_cur_time(self): + return int(time.time()) + + def generate_sig(self, qcloud_app_key, mobile, random_int, now): + fmt = "appkey={}&random={}&time={}&mobile={}" + return hashlib.sha256(fmt.format(qcloud_app_key, random_int, now, mobile)).hexdigest() + + def post(self, path, data): + return self.http_client.post(configs.host, path, data=json.dumps(data)) diff --git a/paas-ce/paas/esb/esb/bkcore/models.py b/paas-ce/paas/esb/esb/bkcore/models.py index 040a5cc5a..c8969cc06 100644 --- a/paas-ce/paas/esb/esb/bkcore/models.py +++ b/paas-ce/paas/esb/esb/bkcore/models.py @@ -9,6 +9,7 @@ """ Core models for the project. """ +import re import json import datetime @@ -94,6 +95,12 @@ def __unicode__(self): def api_path(self): return '/api/c/compapi/%s/' % self.path.strip('/') + @property + def api_version(self): + if self.component_codename.startswith('generic.v2.'): + return 'v2' + return '' + @property def channel_conf(self): return { @@ -229,6 +236,16 @@ def get_extra_headers(self): def get_extra_params(self): return json.loads(self.extra_params or '{}') + @property + def api_path(self): + return '/api/c/self-service-api/%s/' % self.registed_path.strip('/') + + @property + def api_name(self): + path_2_name = re.findall(r'[a-zA-Z0-9]+', self.registed_path.lower()) + path_2_name.insert(0, self.registed_http_method.lower()) + return '_'.join(path_2_name) + class ESBBuffetMapping(models.Model): """ESB 组件自助接入,参数mapping diff --git a/paas-ce/paas/esb/esb/channel/base.py b/paas-ce/paas/esb/esb/channel/base.py index 3ddfe8feb..b77a2fe58 100644 --- a/paas-ce/paas/esb/esb/channel/base.py +++ b/paas-ce/paas/esb/esb/channel/base.py @@ -295,7 +295,8 @@ def get_channel_by_path(self, path, method): for _path in (path, path_another): channel = ESBChannel.objects.filter(path=_path).first() # 从数据库查询出来需要为结果添加channel_classes - if channel: + if channel and method in ['GET', 'POST']: + # 如果通道配置从 DB 获取,则 method 应属于 [GET, POST] try: comp_conf = json.loads(channel.comp_conf) if channel.comp_conf else None if isinstance(comp_conf, (tuple, list)): diff --git a/paas-ce/paas/esb/esb/management/commands/sync_api_docs.py b/paas-ce/paas/esb/esb/management/commands/sync_api_docs.py index d7d39e92f..62c0aa0be 100644 --- a/paas-ce/paas/esb/esb/management/commands/sync_api_docs.py +++ b/paas-ce/paas/esb/esb/management/commands/sync_api_docs.py @@ -28,35 +28,33 @@ class Command(BaseCommand): ) def handle(self, *args, **options): - update_api_docs(is_update_all_api_doc=options['all']) - - -def update_api_docs(is_update_all_api_doc): - # init api docs - api_doc_manager = ApiDocManager() - api_doc_manager.is_update_all_api_doc = is_update_all_api_doc - for channel in ESBChannel.objects.filter(is_active=True, is_hidden=False): - try: - api_data = api_doc_manager.get_api_doc(channel) - except DocNotChangedException: - continue - except Exception as ex: - logger.error('fail to generate apidoc for %s, Exception: %s', channel.component_codename, ex) - continue - - if not api_data: - logger.warning( - 'Oooops, No api document define found in component %(comp_name)s, you better write one.' % - {'comp_name': channel.component_codename}) - continue - - ComponentAPIDoc.objects.update_or_create( - component_id=channel.id, - defaults={ - 'board': '', - 'doc_md': json.dumps(api_data['doc_md']), - 'doc_html': json.dumps(api_data['doc_html']), - 'doc_md_md5': api_data['raw_doc_md_md5'], - } - ) - logger.info('Document synced for api [%s](%s)', api_data['system_name'], api_data['component_name']) + self.update_api_docs(is_update_all_api_doc=options['all']) + + def update_api_docs(self, is_update_all_api_doc): + # init api docs + api_doc_manager = ApiDocManager(is_update_all_api_doc=is_update_all_api_doc) + for channel in ESBChannel.objects.filter(is_active=True, is_hidden=False): + try: + api_data = api_doc_manager.get_api_doc(channel) + except DocNotChangedException: + continue + except Exception as ex: + logger.error('fail to generate apidoc for %s, Exception: %s', channel.component_codename, ex) + continue + + if not api_data: + logger.warning( + 'Oooops, No api document define found in component %(comp_name)s, you better write one.' % + {'comp_name': channel.component_codename}) + continue + + ComponentAPIDoc.objects.update_or_create( + component_id=channel.id, + defaults={ + 'board': '', + 'doc_md': json.dumps(api_data['doc_md']), + 'doc_html': json.dumps(api_data['doc_html']), + 'doc_md_md5': api_data['raw_doc_md_md5'], + } + ) + logger.info('Document synced for api [%s](%s)', api_data['system_name'], api_data['component_name']) diff --git a/paas-ce/paas/esb/esb/management/utils/api_docs.py b/paas-ce/paas/esb/esb/management/utils/api_docs.py index 174451422..94168d11a 100644 --- a/paas-ce/paas/esb/esb/management/utils/api_docs.py +++ b/paas-ce/paas/esb/esb/management/utils/api_docs.py @@ -22,8 +22,8 @@ class ApiDocManager(object): - def __init__(self): - self.is_update_all_api_doc = False + def __init__(self, is_update_all_api_doc=False): + self.is_update_all_api_doc = is_update_all_api_doc self.all_doc_md_md5 = self.get_all_doc_md_md5() def get_api_doc(self, channel): @@ -39,16 +39,15 @@ def get_old_doc_md5(self, path): return self.all_doc_md_md5.get(path) def get_all_doc_md_md5(self): - components = ESBChannel.objects.values_list('id', 'path') - components = dict(components) + components = dict(ESBChannel.objects.values_list('id', 'path')) all_doc_md_md5 = {} api_docs = ComponentAPIDoc.objects.values('component_id', 'doc_md_md5') for api_doc in api_docs: component_id = api_doc['component_id'] - key = components.get(component_id) - if not key: + path = components.get(component_id) + if not path: continue - all_doc_md_md5[key] = api_doc['doc_md_md5'] + all_doc_md_md5[path] = api_doc['doc_md_md5'] return all_doc_md_md5 diff --git a/paas-ce/paas/esb/esb/management/utils/component_tools.py b/paas-ce/paas/esb/esb/management/utils/component_tools.py index bad4e87a7..e80d0cefa 100644 --- a/paas-ce/paas/esb/esb/management/utils/component_tools.py +++ b/paas-ce/paas/esb/esb/management/utils/component_tools.py @@ -6,11 +6,15 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa +import os import re +from importlib import import_module from django.utils import translation from django.template import engines +from common.log import logger +from common.base_utils import read_file, smart_unicode from esb.component.base import get_components_manager from esb.utils.confapis import get_confapis_manager @@ -43,7 +47,6 @@ def get_info(self): 'component_label': self.get_component_label(), 'component_type': self.get_api_type(), 'suggest_method': self.get_suggest_method(), - 'comp_doc': self.comp_doc, 'doc_md': self.get_comp_doc_md(), 'is_confapi': self.is_confapi, 'label_en': self.get_component_label_en(), @@ -66,6 +69,10 @@ def get_api_type(self): return self.comp_class.api_type def get_component_label(self): + api_label = getattr(self.comp_class, 'label', '') + if api_label: + return api_label + api_label = re.search(r'apiLabel\s*(.+)', self.comp_doc) if api_label: api_label = api_label.group(1).strip() @@ -78,9 +85,13 @@ def get_component_label(self): return api_label def get_component_label_en(self): - return '' + return getattr(self.comp_class, 'label_en', '') def get_suggest_method(self): + suggest_method = getattr(self.comp_class, 'suggest_method', '') + if suggest_method: + return suggest_method.upper() + api_method = re.search(r'apiMethod\s*(.+)', self.comp_doc) if api_method: api_method = api_method.group(1).strip() @@ -93,11 +104,45 @@ def get_comp_doc(self): return comp_doc if isinstance(comp_doc, unicode) else comp_doc.decode('utf-8') def get_comp_doc_md(self): + if self.is_comp_doc_md_from_mdfile(): + return self.get_comp_doc_md_from_mdfile() + else: + return self.get_comp_doc_md_from_compdoc() + + def get_comp_doc_md_from_compdoc(self): return { 'en': self.comp_doc, 'zh-hans': self.comp_doc, } + def is_comp_doc_md_from_mdfile(self): + apidoc_en_fpath = self._get_apidoc_fpath(language='en') + apidoc_zhhans_fpath = self._get_apidoc_fpath(language='zh_hans') + if os.path.isfile(apidoc_en_fpath) or os.path.isfile(apidoc_zhhans_fpath): + return True + return False + + def get_comp_doc_md_from_mdfile(self): + apidoc_en = self._get_apidoc_content(language='en') + apidoc_zhhans = self._get_apidoc_content(language='zh_hans') + return { + 'en': smart_unicode(apidoc_en), + 'zh-hans': smart_unicode(apidoc_zhhans), + } + + def _get_apidoc_content(self, language='en'): + fpath = self._get_apidoc_fpath(language=language) + if os.path.isfile(fpath): + try: + return read_file(fpath) + except Exception: + logger.exception('Read file error. fpath=%s', fpath) + return '' + + def _get_apidoc_fpath(self, language='en'): + component_module_path = import_module(self.comp_class.__module__).__file__ + return os.path.join(os.path.dirname(component_module_path), 'apidocs', language, '%s.md' % self.component_name) + class ConfapiComponentClient(ComponentClient): diff --git a/paas-ce/paas/esb/esb/outgoing.py b/paas-ce/paas/esb/esb/outgoing.py index 7f150e1b4..465f75e0f 100644 --- a/paas-ce/paas/esb/esb/outgoing.py +++ b/paas-ce/paas/esb/esb/outgoing.py @@ -110,7 +110,7 @@ def _request(self, method, host, path, params=None, data=None, headers={}, """ Send a request to given destination - :param str method: One of "GET/POST/HEAD/DELETE" + :param str method: One of "GET/POST" :param str host: host, such as "http://www.qq.com/" :param str path: request path, like "/account/login/" :param str/dict params: params in query string @@ -201,7 +201,7 @@ def _request(self, method, host, path, params=None, data=None, headers={}, request_exception=request_exception ) - # GET/POST/HEAD/DELETE requests + # GET/POST requests def get(self, *args, **kwargs): return self.request('GET', *args, **kwargs) @@ -209,12 +209,6 @@ def get(self, *args, **kwargs): def post(self, *args, **kwargs): return self.request('POST', *args, **kwargs) - def head(self, *args, **kwargs): - return self.request('GET', *args, **kwargs) - - def delete(self, *args, **kwargs): - return self.request('POST', *args, **kwargs) - @staticmethod def make_url(host, path, use_test_env): # Tranform SmartHost object to str type @@ -251,6 +245,7 @@ class HttpClient(BasicHttpClient): DEFAULT_HEADERS = [ 'Blueking-Language', + 'Blueking-Timezone', ] def __init__(self, component): @@ -271,6 +266,20 @@ def get_default_headers(self): if key in request_headers ]) + def prepare_bk_header(self, headers={}): + if self.component.request: + bkapi_headers = { + 'X-Bkapi-Request-Id': self.component.request.request_id, + } + else: + bkapi_headers = {} + + request_headers = {} + request_headers.update(self.get_default_headers()) + request_headers.update(bkapi_headers) + request_headers.update(headers) + return request_headers + def request(self, method, host, path, params=None, data=None, headers={}, response_type='json', max_retries=0, response_encoding=None, request_encoding=None, verify=False, cert=None, timeout=None, allow_non_200=False, files=None): @@ -297,8 +306,7 @@ def request(self, method, host, path, params=None, data=None, headers={}, respon if not timeout: timeout = timeout_time if timeout_time else REQUEST_TIMEOUT_SECS - req_headers = self.get_default_headers() - req_headers.update(headers) + req_headers = self.prepare_bk_header(headers) # 调用BasicHttpClient.request来发送请求 r = self._request( diff --git a/paas-ce/paas/esb/esb/utils/base.py b/paas-ce/paas/esb/esb/utils/base.py index 67fadc511..232af0763 100644 --- a/paas-ce/paas/esb/esb/utils/base.py +++ b/paas-ce/paas/esb/esb/utils/base.py @@ -26,6 +26,7 @@ def fpath_to_module(fpath): """Transform a filepath to a module string """ prefix = settings.BASE_DIR + fpath = os.path.normpath(fpath) if fpath.startswith(prefix): fpath = fpath[len(prefix):] # 去掉目录前的斜杠 @@ -116,7 +117,7 @@ def __str__(self): def preprocess_path_tmpl(path): """预处理形如"/users/{username}"的可变路径模板 """ - return RE_PATH_VARIABLE.sub(r'(?P<\1>[\w-]+)', path) + return RE_PATH_VARIABLE.sub(r'(?P<\1>[^/]+)', path) def has_path_vars(path): diff --git a/paas-ce/paas/esb/esb/utils/confapis.py b/paas-ce/paas/esb/esb/utils/confapis.py index 981fc2272..73f726b45 100644 --- a/paas-ce/paas/esb/esb/utils/confapis.py +++ b/paas-ce/paas/esb/esb/utils/confapis.py @@ -24,7 +24,7 @@ class ConfigForm(object): 'label_en': {'required': False}, 'api_type': {'required': False, 'choices': ['query', 'operate']}, 'suggest_method': {'required': False, 'choices': ['GET', 'POST']}, - 'method': {'required': False, 'choices': ['GET', 'POST']}, + 'method': {'required': False, 'choices': ['GET', 'POST', 'PUT', 'DELETE', 'PATCH']}, 'comp_codename': {'required': True}, 'dest_path': {'required': True}, 'dest_http_method': {'required': True, 'choices': ['GET', 'POST', 'PUT', 'DELETE', 'PATCH']}, diff --git a/paas-ce/paas/esb/on_migrate b/paas-ce/paas/esb/on_migrate deleted file mode 100755 index 371c680eb..000000000 --- a/paas-ce/paas/esb/on_migrate +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -source /root/.bkrc -source $CTRL_DIR/functions -export BK_ENV=production - -workon esb || fail "Abort" - -if [ -f esb/management/commands/sync_data_at_deploy.pyc ]; then - python manage.py sync_data_at_deploy -fi diff --git a/paas-ce/paas/esb/requirements.txt b/paas-ce/paas/esb/requirements.txt index 79bd94614..9575ca84b 100644 --- a/paas-ce/paas/esb/requirements.txt +++ b/paas-ce/paas/esb/requirements.txt @@ -14,7 +14,7 @@ pytz==2016.6.1 pycrypto==2.6.1 markdown==2.6.6 -gunicorn==19.6.0 +gunicorn==19.9.0 uWSGI==2.0.13.1 PyYAML==5.1 diff --git a/paas-ce/paas/login/bkaccount/accounts.py b/paas-ce/paas/login/bkaccount/accounts.py index f5b5af874..5f36c5ae7 100644 --- a/paas-ce/paas/login/bkaccount/accounts.py +++ b/paas-ce/paas/login/bkaccount/accounts.py @@ -28,7 +28,7 @@ from common.log import logger from bkaccount.encryption import encrypt, decrypt, salt -from bkaccount.models import Loignlog, BkToken, UserInfo +from bkaccount.models import Loignlog, BkToken class AccountSingleton(object): @@ -119,13 +119,7 @@ def get_bk_token(self, username): retry_count += 1 return bk_token, datetime.datetime.fromtimestamp(expire_time, timezone.get_current_timezone()) - def _is_bk_token_valid(self, bk_token): - """ - 验证用户登录态 - """ - if not bk_token: - error_msg = _("缺少参数bk_token") - return False, None, error_msg + def _decrypt_token(self, bk_token): try: plain_bk_token = decrypt(bk_token) except Exception as error: @@ -135,9 +129,28 @@ def _is_bk_token_valid(self, bk_token): # 参数bk_token非法 error_msg = _("参数bk_token非法") if not plain_bk_token: + return False, error_msg, None + + try: + token_info = plain_bk_token.split('|') + except Exception as error: + token_info = [] + logger.exception("token info wrong, error: {}".format(error)) + + return True, None, token_info + + def _is_bk_token_valid(self, bk_token): + """ + 验证用户登录态 + """ + if not bk_token: + error_msg = _("缺少参数bk_token") + return False, None, error_msg + + ok, error_msg, token_info = self._decrypt_token(bk_token) + if not ok: return False, None, error_msg - token_info = plain_bk_token.split('|') if not token_info or len(token_info) < 3: return False, None, error_msg @@ -315,13 +328,14 @@ def login_success_response(self, request, user_or_form, redirect_to, app_id): expires=expire_time, domain=settings.BK_COOKIE_DOMAIN, httponly=True) + # NOTE: DO NOT SET THE LANGUAGE COOKIE HERE BEFORE I18N is AVAILABLE # set cookie for app or platform - bk_user_info, is_created = UserInfo.objects.get_or_create(user=user) - response.set_cookie(settings.LANGUAGE_COOKIE_NAME, bk_user_info.language, - # max_age=settings.LANGUAGE_COOKIE_AGE, - expires=expire_time, - path=settings.LANGUAGE_COOKIE_PATH, - domain=settings.LANGUAGE_COOKIE_DOMAIN) + # bk_user_info, is_created = UserInfo.objects.get_or_create(user=user) + # response.set_cookie(settings.LANGUAGE_COOKIE_NAME, bk_user_info.language, + # # max_age=settings.LANGUAGE_COOKIE_AGE, + # expires=expire_time, + # path=settings.LANGUAGE_COOKIE_PATH, + # domain=settings.LANGUAGE_COOKIE_DOMAIN) return response def login_redirect_response(self, request, redirect_url, is_from_logout): diff --git a/paas-ce/paas/login/bkaccount/constants.py b/paas-ce/paas/login/bkaccount/constants.py index 172559d9b..06e506749 100644 --- a/paas-ce/paas/login/bkaccount/constants.py +++ b/paas-ce/paas/login/bkaccount/constants.py @@ -35,7 +35,7 @@ ROLECODE_CHOICES = [ (RoleCodeEnum.STAFF, _(u"普通用户")), - (RoleCodeEnum.SUPERUSER, _(u"超级管理员")), + (RoleCodeEnum.SUPERUSER, _(u"管理员")), (RoleCodeEnum.DEVELOPER, _(u"开发者")), (RoleCodeEnum.OPERATOR, _(u"职能化用户")), (RoleCodeEnum.AUDITOR, _(u"审计员")) @@ -63,7 +63,8 @@ SUCCESS=0, PARAM_NOT_VALID=1302100, USER_NOT_EXISTS=1302101, - USER_INFO_UPDATE_FAIL=1302102 + USER_INFO_UPDATE_FAIL=1302102, + USER_NOT_EXISTS2=1302103, ) LanguageEnum = enum( diff --git a/paas-ce/paas/login/bkaccount/forms.py b/paas-ce/paas/login/bkaccount/forms.py index 139595f7f..86f258ad5 100644 --- a/paas-ce/paas/login/bkaccount/forms.py +++ b/paas-ce/paas/login/bkaccount/forms.py @@ -66,8 +66,12 @@ def clean_page_size(self): class BaseUserInfoForm(forms.Form): - chname = forms.CharField(max_length=16) - phone = forms.CharField(max_length=11) + chname = forms.CharField(max_length=16, error_messages={ + "max_length": _("名称长度不能超过16个字符") + }) + phone = forms.CharField(max_length=11, error_messages={ + "max_length": _("手机号长度不能超过11个字符") + }) email = forms.EmailField(max_length=254) def clean_chname(self): diff --git a/paas-ce/paas/login/bkaccount/urls.py b/paas-ce/paas/login/bkaccount/urls.py index 7f7da999c..099a38612 100644 --- a/paas-ce/paas/login/bkaccount/urls.py +++ b/paas-ce/paas/login/bkaccount/urls.py @@ -45,4 +45,8 @@ url(r'^get_user/$', views_api.UserView.as_view()), url(r'^get_all_user/$', views_api.AllUsersView.as_view()), url(r'^get_batch_user/$', views_api.BatchUsersView.as_view()), + + # for legency system, keep below + # user/list + url(r'^$', views.UserPageView.as_view()), ] diff --git a/paas-ce/paas/login/conf/default.py b/paas-ce/paas/login/conf/default.py index bbe9fa04c..59c68f3d7 100644 --- a/paas-ce/paas/login/conf/default.py +++ b/paas-ce/paas/login/conf/default.py @@ -104,7 +104,7 @@ os.path.join(PROJECT_ROOT, 'static'), ) -STATIC_VERSION = '0.0.6' +STATIC_VERSION = '0.0.7' # CSS 文件后缀名 CSS_SUFFIX = 'min.css' diff --git a/paas-ce/paas/login/locale/en/LC_MESSAGES/django.po b/paas-ce/paas/login/locale/en/LC_MESSAGES/django.po index a114935dc..ce58eac8c 100644 --- a/paas-ce/paas/login/locale/en/LC_MESSAGES/django.po +++ b/paas-ce/paas/login/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-03-26 23:33+0800\n" +"POT-Creation-Date: 2019-03-28 20:33+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,546 +17,731 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: .\bkaccount\accounts.py:125 +#: bkaccount/accounts.py:127 msgid "缺少参数bk_token" msgstr "Missing parameters bk_token" -#: .\bkaccount\accounts.py:135 +#: bkaccount/accounts.py:136 msgid "参数bk_token非法" msgstr "Parameters bk_token is illegal" -#: .\bkaccount\accounts.py:146 -#, python-format -msgid "不存在bk_token[%s]的记录" +#: bkaccount/accounts.py:152 +#, fuzzy +#| msgid "不存在bk_token[%s]的记录" +msgid "不存在该bk_token的记录" msgstr "Record of bk_token [%s] does not exist" -#: .\bkaccount\accounts.py:153 +#: bkaccount/accounts.py:159 msgid "登录态已注销" msgstr "login status has been logged out" -#: .\bkaccount\accounts.py:157 +#: bkaccount/accounts.py:163 msgid "登录态已过期" msgstr "Login status has expired" -#: .\bkaccount\accounts.py:161 +#: bkaccount/accounts.py:167 msgid "登录态有效期不合法" msgstr "Login validity is illegal" -#: .\bkaccount\admin.py:20 -msgid "Personal info" -msgstr "" - -#: .\bkaccount\admin.py:21 -msgid "Contact info" -msgstr "" - -#: .\bkaccount\admin.py:22 -msgid "Permissions" -msgstr "" - -#: .\bkaccount\admin.py:23 -msgid "Important dates" -msgstr "" - -#: .\bkaccount\constants.py:33 .\templates\account\user_table.part:46 -#: .\templates\account\user_table.part:54 .\templates\account\users.html:28 +#: bkaccount/constants.py:37 templates/bkaccount/user_table.part:46 +#: templates/bkaccount/user_table.part:54 templates/bkaccount/users.html:27 msgid "普通用户" msgstr "staff" -#: .\bkaccount\constants.py:34 -msgid "超级管理员" +#: bkaccount/constants.py:38 templates/bkaccount/user_table.part:47 +#: templates/bkaccount/users.html:26 +msgid "管理员" msgstr "superuser" -#: .\bkaccount\constants.py:35 .\templates\account\user_table.part:48 -#: .\templates\account\user_table.part:55 .\templates\account\users.html:29 +#: bkaccount/constants.py:39 templates/bkaccount/user_table.part:48 +#: templates/bkaccount/user_table.part:55 templates/bkaccount/users.html:28 msgid "开发者" msgstr "developer" -#: .\bkaccount\constants.py:36 +#: bkaccount/constants.py:40 templates/bkaccount/user_table.part:49 +#: templates/bkaccount/user_table.part:56 templates/bkaccount/users.html:29 msgid "职能化用户" msgstr "operator" -#: .\bkaccount\constants.py:37 .\templates\account\user_table.part:50 -#: .\templates\account\user_table.part:57 .\templates\account\users.html:31 +#: bkaccount/constants.py:41 templates/bkaccount/user_table.part:50 +#: templates/bkaccount/user_table.part:57 templates/bkaccount/users.html:30 msgid "审计员" msgstr "auditor" -#: .\bkaccount\constants.py:71 +#: bkaccount/constants.py:75 msgid "中文" msgstr "Chinese" -#: .\bkaccount\constants.py:72 +#: bkaccount/constants.py:76 msgid "英文" msgstr "English" -#: .\bkaccount\manager.py:52 -#, python-format -msgid "用户名[%s]不存在" -msgstr "Username [%s] does not exist" +#: bkaccount/forms.py:70 +msgid "名称长度不能超过16个字符" +msgstr "" -#: .\bkaccount\manager.py:149 -#, python-format -msgid "用户[%s]密码重置失败" -msgstr "User [%s] password reset failed" +#: bkaccount/forms.py:73 +msgid "手机号长度不能超过11个字符" +msgstr "" -#: .\bkaccount\manager.py:167 -#, python-format -msgid "个人[%s]信息修改失败" +#: bkaccount/forms.py:81 +#, fuzzy +#| msgid "" +#| "中文名【%s】错误,只能包含数字、字母、中文汉字、下划线,长度在1-16个字符" +msgid "中文名错误,只能包含数字、字母、中文汉字、下划线,长度在1-16个字符" +msgstr "" +"Nickname [%s] error, it can only contain numbers, letters and underscores, " +"with a length of 1-16 characters" + +#: bkaccount/forms.py:88 +#, fuzzy +#| msgid "手机号【%s】错误,仅支持中国大陆手机号码(11位数字)" +msgid "手机号错误,仅支持11位数字的号码" +msgstr "Phone number [%s] error, it only supports 10-digit phone number" + +#: bkaccount/forms.py:94 +#, fuzzy +#| msgid "密码不能为空" +msgid "用户名不能为空" +msgstr "Password can not be empty" + +#: bkaccount/forms.py:95 +msgid "用户名长度不能超过20个字符" +msgstr "" + +#: bkaccount/forms.py:96 +msgid "用户名长度不能少于4个字符" +msgstr "" + +#: bkaccount/forms.py:104 +#, fuzzy +#| msgid "" +#| "用户名【%s】错误,只能包含数字、字母、下划线和点,长度在4-20个字符,且必须" +#| "以字母或数字开头" +msgid "" +"用户名错误,只能包含数字、字母、下划线和点,长度在4-20个字符,且必须以字母或" +"数字开头" +msgstr "" +"Username [%s] error, it can only contain numbers, letters, underline and " +"dots, with a length of 4-20 characters and must start with letters or number" + +#: bkaccount/forms.py:110 bkaccount/forms.py:122 bkaccount/forms.py:132 +#, fuzzy +#| msgid "密码不能为空" +msgid "新密码不能为空" +msgstr "Password can not be empty" + +#: bkaccount/forms.py:111 bkaccount/forms.py:133 +msgid "密码长度不能超过20个字符" +msgstr "" + +#: bkaccount/forms.py:112 bkaccount/forms.py:134 +msgid "密码长度不能少于8个字符" +msgstr "" + +#: bkaccount/forms.py:124 +msgid "两次输入的新密码不一致" +msgstr "Two passwords entered in twice are not the same" + +#: bkaccount/forms.py:126 bkaccount/forms.py:141 +msgid "" +"密码只支持数字、字母或!@#$%^*()_-+=,长度在8-20个字符,且必须保证包含大小写字" +"母和数字" +msgstr "" +"The password only supports numbers, letters, or !@#$%^*()_-+=, with a length " +"of 8 to 20 characters and must contain uppercase and lowercase and numbers" + +#: bkaccount/forms.py:146 +#, fuzzy +#| msgid "参数错误,wx_userid 不能为空" +msgid "wx_userid 不能为空" +msgstr "Parameter error, wx_userid cannot be empty" + +#: bkaccount/forms.py:150 +msgid "文件必须上传" +msgstr "" + +#: bkaccount/forms.py:157 +#, fuzzy +#| msgid "批量导入用户,解析文件名出错:%s" +msgid "批量导入用户,解析文件名出错" +msgstr "Batch import users, file name parse error: %s" + +#: bkaccount/forms.py:159 +msgid "文件格式错误,只支持:.xls 和 .xlsx 文件" +msgstr "File format error, only supports files in .xls and .xlsx formats" + +#: bkaccount/manager.py:61 +msgid "用户名不存在" +msgstr "" + +#: bkaccount/manager.py:159 bkaccount/manager.py:325 +msgid "用户密码重置失败" +msgstr "User password reset failed" + +#: bkaccount/manager.py:176 +#, fuzzy +#| msgid "个人[%s]信息修改失败" +msgid "个人信息修改失败" msgstr "[%s] Personal information modification failed" -#: .\bkaccount\manager.py:194 .\bkaccount\manager.py:235 -#, python-format -msgid "账号为:%s 的用户是最后一个管理员,不可修改其角色" +#: bkaccount/manager.py:201 +#, fuzzy +#| msgid "账号为:%s 的用户是最后一个管理员,不可修改其角色" +msgid "该用户是最后一个管理员,不可修改其角色" msgstr "" "Username: %s user is the last administrator, and his role cannot be modified" -#: .\bkaccount\manager.py:260 -#, python-format -msgid "账号为:%s 的用户已经存在" +#: bkaccount/manager.py:242 +#, fuzzy +#| msgid "账号为:%s 的用户是最后一个管理员,不可修改其角色" +msgid "用户是最后一个管理员,不可修改其角色" +msgstr "" +"Username: %s user is the last administrator, and his role cannot be modified" + +#: bkaccount/manager.py:267 +#, fuzzy +#| msgid "账号为:%s 的用户已经存在" +msgid "用户已经存在" msgstr "Username: %s user already exists" -#: .\bkaccount\manager.py:263 -#, python-format -msgid "保存用户信息(%s)出错" +#: bkaccount/manager.py:270 +#, fuzzy +#| msgid "保存用户信息(%s)出错" +msgid "保存用户信息出错" msgstr "Save user(%s) information failed" -#: .\bkaccount\manager.py:296 +#: bkaccount/manager.py:303 msgid "内置admin用户不可删除" msgstr "Built in admin user cannot be deleted" -#: .\bkaccount\manager.py:299 +#: bkaccount/manager.py:306 msgid "最后一个管理员用户,不允许删除" msgstr "The user as the last administrator is not permitted to be deleted" -#: .\bkaccount\manager.py:304 -#, python-format -msgid "用户(%s)删除失败" +#: bkaccount/manager.py:311 +#, fuzzy +#| msgid "用户(%s)删除失败" +msgid "用户删除失败" msgstr "User (%s) delete failed" -#: .\bkaccount\manager.py:318 -msgid "用户密码重置失败" -msgstr "User password reset failed" - -#: .\bkaccount\manager.py:328 +#: bkaccount/manager.py:335 msgid "已经绑定了微信,请解绑后再重新绑定!" msgstr "WeChat has been bound, please unbind and then bind again" -#: .\bkaccount\manager.py:332 +#: bkaccount/manager.py:339 msgid "该微信号已经被绑定过了" msgstr "The WeChat ID has been bound" -#: .\bkaccount\manager.py:339 +#: bkaccount/manager.py:346 msgid "绑定用户微信信息失败" msgstr "Bound user WeChat information failed" -#: .\bkaccount\manager.py:350 +#: bkaccount/manager.py:357 msgid "账号未绑定过微信号,无法解绑" msgstr "The user has not been bound with a WeChat ID, so it cannot be unbound" -#: .\bkaccount\manager.py:354 +#: bkaccount/manager.py:361 msgid "解绑用户微信信息失败" msgstr "Unbound user WeChat information failed" -#: .\bkaccount\manager.py:385 +#: bkaccount/manager.py:392 msgid "记录成功" msgstr "Record succeeded" -#: .\bkaccount\manager.py:387 +#: bkaccount/manager.py:394 msgid "用户登录记录失败" msgstr "User login record failed" -#: .\bkaccount\models.py:43 +#: bkaccount/models.py:51 msgid "date joined" msgstr "" -#: .\bkaccount\models.py:51 +#: bkaccount/models.py:59 msgid "user" msgstr "" -#: .\bkaccount\models.py:52 +#: bkaccount/models.py:60 msgid "users" msgstr "" -#: .\bkaccount\models.py:123 +#: bkaccount/models.py:125 msgid "create_time" msgstr "" -#: .\bkaccount\utils.py:83 -#, python-format -msgid "导出数据出现错误:%s" -msgstr "Export data error: %s" - -#: .\bkaccount\validators.py:16 -#, python-format -msgid "" -"用户名【%s】错误,只能包含数字、字母、下划线和点,长度在4-20个字符,且必须以" -"字母或数字开头" -msgstr "" -"Username [%s] error, it can only contain numbers, letters, underline and " -"dots, with a length of 4-20 characters and must start with letters or number" - -#: .\bkaccount\validators.py:25 -#, python-format -msgid "" -"中文名【%s】错误,只能包含数字、字母、中文汉字、下划线,长度在1-16个字符" -msgstr "" -"Nickname [%s] error, it can only contain numbers, letters and underscores, " -"with a length of 1-16 characters" - -#: .\bkaccount\validators.py:34 -#, python-format -msgid "手机号【%s】错误,仅支持中国大陆手机号码(11位数字)" -msgstr "Phone number [%s] error, it only supports 10-digit phone number" - -#: .\bkaccount\validators.py:43 -#, python-format -msgid "email【%s】格式错误" -msgstr "Email format [%s] error" - -#: .\bkaccount\validators.py:52 -msgid "" -"密码只支持数字、字母或!@#$%^*()_-+=,长度在8-20个字符,且必须保证包含大小写字" -"母和数字" +#: bkaccount/utils.py:36 +msgid "用户不存在" msgstr "" -"The password only supports numbers, letters, or !@#$%^*()_-+=, with a length " -"of 8 to 20 characters and must contain uppercase and lowercase and numbers" -#: .\bkaccount\validators.py:61 -msgid "密码不能为空" -msgstr "Password can not be empty" - -#: .\bkaccount\validators.py:63 -msgid "两次输入的新密码不一致" -msgstr "Two passwords entered in twice are not the same" +#: bkaccount/utils.py:96 +#, fuzzy +#| msgid "导出数据出现错误:%s" +msgid "导出数据出现错误" +msgstr "Export data error: %s" -#: .\bkaccount\validators.py:80 -#, python-format -msgid "用户%s不存在" -msgstr "User [%s] does not exist" +#: bkaccount/views.py:147 +msgid "保存用户信息成功" +msgstr "Save user information succeeded" -#: .\bkaccount\validators.py:99 -#, python-format -msgid "批量导入用户,解析文件名出错:%s" -msgstr "Batch import users, file name parse error: %s" +#: bkaccount/views.py:159 +#, fuzzy +#| msgid "用户(%s)删除成功" +msgid "用户删除成功" +msgstr "User (%s) delete succeeded " -#: .\bkaccount\validators.py:102 -msgid "文件格式错误,只支持:.xls 和 .xlsx 文件" -msgstr "File format error, only supports files in .xls and .xlsx formats" +#: bkaccount/views.py:175 +#, fuzzy +#| msgid "修改密码" +msgid "修改密码成功" +msgstr "Change Password" -#: .\bkaccount\views.py:115 .\bkaccount\views.py:142 .\bkaccount\views.py:161 -#: .\bkaccount\views.py:189 .\role_manage\views.py:56 -msgid "非管理员用户, 没有权限进行操作, 请找管理员申请权限!" +#: bkaccount/views.py:183 common/mixins/base.py:31 common/mixins/base.py:45 +#, fuzzy +#| msgid "非管理员用户, 没有权限进行操作, 请找管理员申请权限!" +msgid "非管理员, 没有权限进行操作, 请找管理员申请权限!" msgstr "" "Non-administrator users do not have permissions to operate, so please apply " "for permissions to the administrator." -#: .\bkaccount\views.py:131 -msgid "保存用户信息成功" -msgstr "Save user information succeeded" - -#: .\bkaccount\views.py:150 -#, python-format -msgid "用户(%s)删除成功" -msgstr "User (%s) delete succeeded " - -#: .\bkaccount\views.py:203 +#: bkaccount/views.py:196 msgid "文件解析出错,请下载 EXCEL模板文件 填写用户数据" msgstr "" "File parse error, please download EXCEL template file and fill in user data" -#: .\bkaccount\views.py:207 -msgid "导入数据为空" +#: bkaccount/views.py:199 +#, fuzzy +#| msgid "导入数据为空" +msgid "导入数据不能为空" msgstr "Import data is empty" -#: .\bkaccount\views.py:240 -#, python-format -msgid "用户导入出现异常%s" +#: bkaccount/views.py:219 +#, fuzzy +#| msgid "用户导入出现异常%s" +msgid "用户导入出现异常 {}" msgstr "An exception occurred while user importing data; %s" -#: .\bkaccount\views.py:242 -msgid "用户导入成功" -msgstr "User import succeeded" - -#: .\bkaccount\views.py:258 .\templates\account\user_role_manage_table.part:26 -#: .\templates\account\user_table.part:19 +#: bkaccount/views.py:230 templates/bkaccount/user_table.part:19 msgid "用户名" msgstr "username" -#: .\bkaccount\views.py:258 .\templates\account\user_table.part:20 +#: bkaccount/views.py:230 templates/bkaccount/user_table.part:20 msgid "中文名" msgstr "nickname" -#: .\bkaccount\views.py:258 .\templates\account\user_table.part:21 +#: bkaccount/views.py:230 templates/bkaccount/user_table.part:21 msgid "联系电话" msgstr "phone" -#: .\bkaccount\views.py:258 .\templates\account\user_table.part:22 +#: bkaccount/views.py:230 templates/bkaccount/user_table.part:22 msgid "常用邮箱" msgstr "email" -#: .\bkaccount\views.py:258 .\templates\account\user_table.part:23 +#: bkaccount/views.py:230 templates/bkaccount/user_table.part:23 msgid "角色" msgstr "role" -#: .\bkaccount\views_api.py:26 .\bkaccount\views_api_v2.py:29 +#: bkaccount/views_api.py:31 bkaccount/views_api_v2.py:29 msgid "用户验证成功" msgstr "User authentication succeeded" -#: .\bkaccount\views_api.py:50 .\bkaccount\views_api.py:70 -#: .\bkaccount\views_api.py:99 .\bkaccount\views_api_v2.py:54 -#: .\bkaccount\views_api_v2.py:75 .\bkaccount\views_api_v2.py:105 -#: .\role_manage\views_api.py:40 .\role_manage\views_api_v2.py:42 +#: bkaccount/views_api.py:52 bkaccount/views_api.py:69 +#: bkaccount/views_api.py:92 bkaccount/views_api_v2.py:50 +#: bkaccount/views_api_v2.py:67 bkaccount/views_api_v2.py:90 msgid "用户信息获取成功" msgstr "Get user information succeeded" -#: .\bkaccount\views_api.py:84 .\bkaccount\views_api.py:112 -#: .\bkaccount\views_api.py:150 .\bkaccount\views_api.py:191 -#: .\bkaccount\views_api.py:224 .\bkaccount\views_api.py:254 -#: .\bkaccount\views_api.py:279 .\bkaccount\views_api_v2.py:90 -#: .\role_manage\views_api.py:25 .\role_manage\views_api_v2.py:27 +#: bkaccount/views_api.py:77 bkaccount/views_api.py:100 +#: bkaccount/views_api.py:121 bkaccount/views_api.py:144 +#: bkaccount/views_api_v2.py:75 msgid "请求参数格式错误,必须为json格式" msgstr "Request parameters format error, it must be in json format" -#: .\bkaccount\views_api.py:95 .\role_manage\views_api.py:36 +#: bkaccount/views_api.py:88 msgid "缺少参数:username_list" msgstr "Missing parameters: username_list" -#: .\bkaccount\views_api.py:123 .\bkaccount\views_api.py:161 -#: .\bkaccount\views_api.py:201 -msgid "您的权限不足" -msgstr "Your permission is insufficient" - -#: .\bkaccount\views_api.py:137 +#: bkaccount/views_api.py:113 msgid "密码重置成功" msgstr "Password reset succeeded" -#: .\bkaccount\views_api.py:178 +#: bkaccount/views_api.py:136 msgid "用户信息修改成功" msgstr "User information modification succeeded" -#: .\bkaccount\views_api.py:211 -msgid "用户角色修改成功" -msgstr "User role modification succeeded" - -#: .\bkaccount\views_api.py:234 -msgid "参数错误,wx_userid 不能为空" -msgstr "Parameter error, wx_userid cannot be empty" - -#: .\bkaccount\views_api.py:241 +#: bkaccount/views_api.py:157 msgid "绑定成功" msgstr "Binding succeeded" -#: .\bkaccount\views_api.py:266 +#: bkaccount/views_api.py:165 msgid "解绑成功" msgstr "Unbinding succeeded" -#: .\bkaccount\views_api.py:290 -msgid "参数错误,language和timezone不能同时为空" -msgstr "" -"Parameter error, language and timezone can not both be empty at the same time" - -#: .\bkaccount\views_api.py:293 -msgid "设置成功" -msgstr "Set successfully" - -#: .\bkaccount\views_api_v2.py:101 .\role_manage\views_api_v2.py:38 +#: bkaccount/views_api_v2.py:86 #, fuzzy #| msgid "缺少参数:username_list" msgid "缺少参数:bk_username_list" msgstr "Missing parameters: username_list" -#: .\common\license_utils.py:28 -#, python-format -msgid "证书文件(platform.cert)不存在: %s" -msgstr "Certificate file (platform.cert) does not exist: %s" - -#: .\common\license_utils.py:31 -#, python-format -msgid "密钥文件(platform.key)不存在: %s" -msgstr "Secret key file (platform.key) does not exist: %s" +#: conf/default.py:183 +msgid "English" +msgstr "英文" -#: .\common\license_utils.py:39 -msgid "证书文件(platform.cert)为空或已被损坏" -msgstr "Certificate file (platform.cert) is empty or has been damaged" +#: conf/default.py:184 +msgid "简体中文" +msgstr "Simplified Chinese" -#: .\common\license_utils.py:55 -msgid "license_server请求校验证书异常" +#: healthz/views.py:44 +#, fuzzy +#| msgid "配置文件不正确, 缺失对应配置: %s" +msgid "配置文件不正确, 缺失对应配置: {}" msgstr "" -"Exceptions occurred in request license server to certificate validation" +"Configuration file is incorrect, with corresponding configurations missed: %s" + +#: healthz/views.py:54 +#, fuzzy +#| msgid "数据库连接存在问题: %s" +msgid "数据库连接存在问题: {}" +msgstr "There is a problem with database connection: %s" + +#: templates/401.html:6 +msgid "未登录蓝鲸智云平台(401页)" +msgstr "Have not logged in BlueKing platform (page 401)" + +#: templates/401.html:20 +msgid "您需要登录蓝鲸智云" +msgstr "You need to log in BlueKing" + +#: templates/401.html:21 +msgid "立即登录" +msgstr "Log in right now" + +#: templates/403.html:6 +msgid "您没有访问权限(403页)" +msgstr "You have no access permissions (Page 403)" -#: .\common\license_utils.py:108 -msgid "证书不可用,请求未返回有效期或返回格式有误" +#: templates/403.html:20 +msgid "您没有访问权限,请联系系统管理员添加" msgstr "" -"Certificate is not available, the request did not return a valid period or " -"the return format is incorrect" +"You have no access permissions, please contact system administrator to add" -#: .\common\license_utils.py:109 -msgid "证书校验成功" -msgstr "Certificate validation succeeded" +#: templates/404.html:6 +msgid "页面找不到(404页)" +msgstr "Page Not Found (404)" -#: .\conf\default.py:182 -msgid "English" -msgstr "英文" +#: templates/404.html:20 +msgid "页面找不到了" +msgstr "Page Not Found" -#: .\conf\default.py:183 -msgid "简体中文" -msgstr "Simplified Chinese" +#: templates/500.html:6 +msgid "系统异常(500页)" +msgstr "System exception (page 500)" -#: .\healthz\views.py:67 -#, python-format -msgid "配置文件不正确, 缺失对应配置: %s" +#: templates/500.html:20 +msgid "系统出现异常" +msgstr "Exceptions occurred in system" + +#: templates/500.html:21 +msgid "努力恢复中,请稍后再试......" +msgstr "Trying to recover, please try again later..." + +#: templates/50x.html:6 templates/50x.html.py:19 +msgid "服务故障,努力修复中..." +msgstr "Service failure, trying to repair ..." + +#: templates/50x.html:20 +msgid "服务出现故障,我们正在紧急修复,给您带来不便,敬请谅解。" msgstr "" -"Configuration file is incorrect, with corresponding configurations missed: %s" +"Service failure, we are trying our best to do emergency repair. Please " +"understand for the inconvenience." -#: .\healthz\views.py:78 -#, python-format -msgid "数据库连接存在问题: %s" -msgstr "There is a problem with database connection: %s" +#: templates/bkaccount/base.html:11 +#, fuzzy +#| msgid "用户管理|蓝鲸智云企业版" +msgid "用户管理|蓝鲸智云社区版" +msgstr "User Management|BlueKing" -#: .\healthz\views.py:87 -#, python-format -msgid "企业证书无效:%s; 只影响桌面版本信息的展示" +#: templates/bkaccount/base.html:12 +#, fuzzy +#| msgid "" +#| "开发者中心,游戏运维,运维,服务器管理,模块配置,监控,腾讯游戏,蓝鲸,智云," +#| "devops,运维开发,蓝鲸企业版,企业版,作业平台,集成平台,配置平台,管控平台" +msgid "" +"开发者中心,游戏运维,运维,服务器管理,模块配置,监控,腾讯游戏,蓝鲸,智云,devops," +"运维开发,蓝鲸社区版,社区版,作业平台,集成平台,配置平台,管控平台" msgstr "" -"Enterprise certificate is invalid: %s; it just has an impact on the " -"demonstration of desktop version information " +"Developer Center, Game OPS, OPS, Server Management, Module Configuration, " +"Monitoring, Tencent Game, BlueKing, DevOps, OPS Development, BlueKing " +"Enterprise, Enterprise, Job System, Integration System, Configuration " +"System, Control System" -#: .\role_manage\constants.py:6 -msgid "管控平台" -msgstr "Control System" +#: templates/bkaccount/base.html:13 +#, fuzzy +#| msgid "" +#| "蓝鲸智云软件企业版是由蓝鲸智云团队提供的一套基于PaaS的技术解决方案,旨在改" +#| "变中国运维行业,帮助企业快速达到基础运维支撑能力,并提升技术人员的DevOps能" +#| "力。该版本提供了配置平台,作业平台,集成平台等强大功能,用户在使用时,请查" +#| "阅并遵守《蓝鲸智云软件用户服务协议》。" +msgid "" +"蓝鲸智云软件社区版是由蓝鲸智云团队提供的一套基于PaaS的技术解决方案,旨在改变" +"中国运维行业,帮助企业快速达到基础运维支撑能力,并提升技术人员的DevOps能力。" +"该版本提供了配置平台,作业平台,集成平台等强大功能,用户在使用时,请查阅并遵" +"守《蓝鲸智云软件用户服务协议》。" +msgstr "" +"BlueKing Enterprise is a PaaS-based technology solution developed by " +"BlueKing team, aiming at changing the OPS industry in China, helping " +"enterprises rapidly achieve basic OPS support capability and enhancing " +"technical staff's DevOps capabilities. It supports CC/JOB/PaaS." -#: .\role_manage\constants.py:7 -msgid "作业平台" -msgstr "Job System" +#: templates/bkaccount/base.html:43 templates/bkaccount/base.html.py:98 +#: templates/login/login.html:54 +#, fuzzy +#| msgid "蓝鲸智云后台管理" +msgid "蓝鲸智云工作台" +msgstr "BlueKing Backstage management" -#: .\role_manage\constants.py:8 -msgid "配置平台" -msgstr "Configuration System" +#: templates/bkaccount/base.html:44 +msgid "img/logo/logo_user_01.png" +msgstr "img/logo/logo_user_01_en.png" -#: .\role_manage\constants.py:9 -msgid "集成平台" -msgstr "Integration System" +#: templates/bkaccount/base.html:46 +msgid "蓝鲸智云用户管理" +msgstr "BlueKing User Management" -#: .\role_manage\constants.py:10 -msgid "网络平台" -msgstr "Network System" +#: templates/bkaccount/base.html:47 +msgid "img/logo/logo_user_02.png" +msgstr "img/logo/logo_user_02_en.png" -#: .\role_manage\constants.py:11 -msgid "蓝鲸监控" -msgstr "BK Monitor" +#: templates/bkaccount/base.html:68 +msgid "注销" +msgstr "Logout" -#: .\role_manage\constants.py:12 -msgid "日志检索" -msgstr "Log-Search" +#: templates/bkaccount/base.html:83 +msgid "返回顶部" +msgstr "Back top" -#: .\role_manage\constants.py:13 -msgid "故障自愈" -msgstr "Fault Auto-recovery" +#: templates/bkaccount/base.html:86 +msgid "返回底部" +msgstr "Back bottom" -#: .\role_manage\constants.py:14 -msgid "标准运维" -msgstr "Standard OPS" +#: templates/bkaccount/base.html:95 templates/login/login.html:51 +msgid "QQ咨询" +msgstr "QQ" -#: .\role_manage\constants.py:15 -msgid "Agent安装" -msgstr "Agent Install" +#: templates/bkaccount/base.html:96 templates/login/login.html:52 +msgid "蓝鲸论坛" +msgstr "BlueKing Forum" -#: .\role_manage\constants.py:16 -msgid "数据平台" -msgstr "Data System" +#: templates/bkaccount/base.html:97 templates/login/login.html:53 +msgid "蓝鲸官网" +msgstr "Blueking Official" -#: .\role_manage\constants.py:17 -msgid "数据平台官网" -msgstr "DataWeb" +#: templates/bkaccount/base.html:101 +msgid "蓝鲸智云 版权所有" +msgstr " " + +#: templates/bkaccount/user_table.part:24 +msgid "操作" +msgstr "operation" + +#: templates/bkaccount/user_table.part:62 +msgid "取消" +msgstr "Cancel" + +#: templates/bkaccount/user_table.part:63 +msgid "保存" +msgstr "Save" -#: .\role_manage\constants.py:18 -msgid "开发框架" -msgstr "Python Framework" +#: templates/bkaccount/user_table.part:64 +msgid "编辑" +msgstr "Edit" -#: .\role_manage\constants.py:19 -msgid "开发样例" -msgstr "Python Framework demo" +#: templates/bkaccount/user_table.part:65 +msgid "重置密码" +msgstr "Reset Passowrd" -#: .\role_manage\constants.py:20 -msgid "包管理" -msgstr "CDMan" +#: templates/bkaccount/user_table.part:67 +msgid "删除" +msgstr "Delete" -#: .\role_manage\constants.py:21 -msgid "审批系统" -msgstr "Approval System" +#: templates/bkaccount/user_table.part:73 +msgid "没有数据" +msgstr "No data" -#: .\role_manage\constants.py:22 -msgid "经费管理" -msgstr "Funds Manage" +#: templates/bkaccount/user_table.part:85 +#: templates/bkaccount/user_table.part:87 +msgid "上一页" +msgstr "Previous" -#: .\role_manage\constants.py:23 -msgid "会议管理" -msgstr "Meeting Manage" +#: templates/bkaccount/user_table.part:109 +#: templates/bkaccount/user_table.part:111 +msgid "下一页" +msgstr "Next" -#: .\role_manage\constants.py:27 .\templates\account\user_table.part:47 -#: .\templates\account\users.html:27 -msgid "管理员" -msgstr "superuser" +#: templates/bkaccount/users.html:11 +msgid "导出" +msgstr "Export" -#: .\role_manage\constants.py:28 -msgid "操作员" -msgstr "operator" +#: templates/bkaccount/users.html:12 +msgid "批量导入" +msgstr "Batch import" -#: .\role_manage\views.py:63 -msgid "保存成功" -msgstr "Save succeeded" +#: templates/bkaccount/users.html:13 +msgid "新增用户" +msgstr "Add user" + +#: templates/bkaccount/users.html:15 +msgid "用户信息" +msgstr "User information" + +#: templates/bkaccount/users.html:23 +msgid "查询:按用户名、中文名" +msgstr "search: by username, nickname" + +#: templates/bkaccount/users.html:25 +msgid "所有用户" +msgstr "All users" + +#: templates/bkaccount/users.html:32 +msgid "查询" +msgstr "Search" + +#: templates/bkaccount/users.html:33 +msgid "新增用户的默认密码为:" +msgstr "Default password of new user is " + +#: templates/bkaccount/users.html:38 +msgid "温馨提示:" +msgstr "Tips:" + +#: templates/bkaccount/users.html:41 +#, fuzzy +#| msgid "" +#| "

管理员可以管理所有用户的信息,具有所有权限

普" +#| "通用户可以管理自己的用户信息和访问 “桌面”

开发者可以管理自己的用户信息、访问 “桌面” 和访问 “开发者中心”

" +#| "职能化用户在普通用户权限上还拥有SaaS应用 “标准运维” 的职能化权限

审计员在普通用户权限上还拥有SaaS应用 “标准运维”和作业平" +#| "台的审计权限

" +msgid "" +"

管理员可以管理所有用户的信息,具有所有权限

普通" +"用户可以管理自己的用户信息和访问 “工作台”

开发者可" +"以管理自己的用户信息、访问 “工作台” 和访问 “开发者中心”

职能化用" +"户在普通用户权限上还拥有SaaS应用 “标准运维” 的职能化权限

" +"审计员在普通用户权限上还拥有SaaS应用 “标准运维”和作业平台的审计权限" +msgstr "" +"

Superusercan manage the information of all users, provided " +"with all permissions

Staffcan manage the user information " +"of his own and access the blueking desktop

Developercan " +"manage the user information of his own, and can access the blueking desktop " +"and developer center

Operatorowns the operation " +"permission of SaaS APP - Standard OPS, in addition the permissions of common " +"users

Auditorowns the audit permission of SaaS APP - " +"Standard OPS and Job System, in addition the permissions of common users

" + +#: templates/bkaccount/users.html:55 +msgid "选择文件:" +msgstr "Select file:" + +#: templates/bkaccount/users.html:57 +msgid "导入用户" +msgstr "Import user" -#: .\templates\401.html:6 -msgid "未登录蓝鲸智云平台(401页)" -msgstr "Have not logged in BlueKing platform (page 401)" +#: templates/bkaccount/users.html:58 +msgid "提交" +msgstr "Submit" -#: .\templates\401.html:20 -msgid "您需要登录蓝鲸智云" -msgstr "You need to log in BlueKing" +#: templates/bkaccount/users.html:61 +msgid "bk_user_import.xls" +msgstr "bk_user_import_en.xls" -#: .\templates\401.html:21 -msgid "立即登录" -msgstr "Log in right now" +#: templates/bkaccount/users.html:61 +msgid "点击下载EXCEL模板" +msgstr "Click to download EXCEL template" -#: .\templates\403.html:6 -msgid "您没有访问权限(403页)" -msgstr "You have no access permissions (Page 403)" +#: templates/bkaccount/users.html:65 +msgid "注意:" +msgstr "Note:" -#: .\templates\403.html:20 -msgid "您没有访问权限,请联系系统管理员添加" +#: templates/bkaccount/users.html:66 +#, fuzzy, python-format +#| msgid "" +#| "

1.请下载EXCEL模板文件" +#| "填写用户数据

2.用户名为必填,包含数字和字母,长度在" +#| "4-20个字符

3.用户名为唯一标识,重复导入会覆盖已有数据" +#| "

4.导入用户默认密码为:%(default_paasword)s

5." +#| "文件后缀名必须为:.xls.xlsx

6.导入失败" +#| "请检查EXCEL格式规范,或重新下载模板填写

" +msgid "" +"

1.请下载EXCEL模板文件填写" +"用户数据

2.用户名为必填,包含数字、字母、下划线和点,长度" +"在4-20个字符

3.用户名为唯一标识,重复导入会覆盖已有数据

4.导入用户默认密码为:%(default_paasword)s

5.文件后" +"缀名必须为:.xls.xlsx

6.导入失败请检查" +"EXCEL格式规范,或重新下载模板填写

" msgstr "" -"You have no access permissions, please contact system administrator to add" +"

1. Please download EXCEL " +"template file and fill in user data

2.Username is " +"required, including numbers and letters, the length of 4-20 characters

3.Username a unique identifier, duplicate import will " +"overwrite existing data

4. Default passowrd of imported users: " +"%(default_paasword)s

5. The file extension must be .xls or .xlsx

6. If import failed, please check the " +"EXCEL format specification, or re-download the template to fill in

" -#: .\templates\404.html:6 -msgid "页面找不到(404页)" -msgstr "Page Not Found (404)" +#: templates/bkaccount/users.html:81 +msgid "新密码:" +msgstr "Password: " -#: .\templates\404.html:20 -msgid "页面找不到了" -msgstr "Page Not Found" +#: templates/bkaccount/users.html:86 templates/bkaccount/users.html.py:92 +msgid "必填" +msgstr "Required" -#: .\templates\500.html:6 -msgid "系统异常(500页)" -msgstr "System exception (page 500)" +#: templates/bkaccount/users.html:87 +#, python-format +msgid "" +"请输入密码,长度在8-20个字符,可支持数字、字母以及%(sp_char)s,必须保证密码包" +"含大小写字母和数字 " +msgstr "" +"Please enter the password, the length of 8-20 characters, support numbers, " +"letters and %(sp_char)s, must ensure that the password contains uppercase " +"letters and numbers" -#: .\templates\500.html:20 -msgid "系统出现异常" -msgstr "Exceptions occurred in system" +#: templates/bkaccount/users.html:90 +msgid "确认密码" +msgstr "Comfirm" -#: .\templates\500.html:21 -msgid "努力恢复中,请稍后再试......" -msgstr "Trying to recover, please try again later..." +#: templates/bkaccount/users.html:91 +msgid "再次输入密码" +msgstr "Input password again" -#: .\templates\50x.html:6 .\templates\50x.html.py:19 -msgid "服务故障,努力修复中..." -msgstr "Service failure, trying to repair ..." +#: templates/csrf_failure.html:6 templates/csrf_failure.html.py:20 +msgid "CSRF验证失败" +msgstr "CSRF verification failed" -#: .\templates\50x.html:20 -msgid "服务出现故障,我们正在紧急修复,给您带来不便,敬请谅解。" +#: templates/csrf_failure.html:22 +msgid "" +"您看到此消息是由于该站点在提交表单时需要一个CSRF cookie。此项是出于安全考虑," +"以确保您的浏览器没有被第三方劫持。" msgstr "" -"Service failure, we are trying our best to do emergency repair. Please " -"understand for the inconvenience." +"You see this message because the site needs a CSRF cookie when submitting " +"the form. This is for security reasons to make sure your browser is not " +"hijacked by a third party." + +#: templates/csrf_failure.html:23 +msgid "" +"如果您已经设置浏览器禁用cookies,请重新启用,至少针对这个站点,全部HTTPS请" +"求,或者同源请求(same-origin)启用cookies。" +msgstr "" +"If you have set your browser to disable cookies, please enable it again, " +"enabling cookies at least for this site, for all HTTPS requests, or same-" +"origin requests." -#: .\templates\account\agreement.part:6 +#: templates/csrf_failure.html:24 +msgid "重新登录" +msgstr "Login again" + +#: templates/login/agreement.part:6 msgid "" "
腾讯蓝鲸智云软件许可及服务协议

【首部及导言】

欢迎您使用腾讯蓝鲸" @@ -1107,373 +1292,217 @@ msgstr "" "any version of other language, the Chinese version shall prevail. (End)

Tencent

" -#: .\templates\account\agreement.part:124 +#: templates/login/agreement.part:124 msgid "已阅读" msgstr "I know" -#: .\templates\account\base.html:11 -msgid "用户管理|蓝鲸智云企业版" -msgstr "User Management|BlueKing" - -#: .\templates\account\base.html:12 -msgid "" -"开发者中心,游戏运维,运维,服务器管理,模块配置,监控,腾讯游戏,蓝鲸,智云,devops," -"运维开发,蓝鲸企业版,企业版,作业平台,集成平台,配置平台,管控平台" -msgstr "" -"Developer Center, Game OPS, OPS, Server Management, Module Configuration, " -"Monitoring, Tencent Game, BlueKing, DevOps, OPS Development, BlueKing " -"Enterprise, Enterprise, Job System, Integration System, Configuration " -"System, Control System" - -#: .\templates\account\base.html:13 -msgid "" -"蓝鲸智云软件企业版是由蓝鲸智云团队提供的一套基于PaaS的技术解决方案,旨在改变" -"中国运维行业,帮助企业快速达到基础运维支撑能力,并提升技术人员的DevOps能力。" -"该版本提供了配置平台,作业平台,集成平台等强大功能,用户在使用时,请查阅并遵" -"守《蓝鲸智云软件用户服务协议》。" -msgstr "" -"BlueKing Enterprise is a PaaS-based technology solution developed by " -"BlueKing team, aiming at changing the OPS industry in China, helping " -"enterprises rapidly achieve basic OPS support capability and enhancing " -"technical staff's DevOps capabilities. It supports CC/JOB/PaaS." - -#: .\templates\account\base.html:42 .\templates\account\base.html.py:97 -#: .\templates\account\login.html:69 -msgid "蓝鲸智云桌面" -msgstr "BlueKing Desktop" - -#: .\templates\account\base.html:43 -msgid "img/logo/logo_user_01.png" -msgstr "img/logo/logo_user_01_en.png" - -#: .\templates\account\base.html:45 -msgid "蓝鲸智云用户管理" -msgstr "BlueKing User Management" - -#: .\templates\account\base.html:46 -msgid "img/logo/logo_user_02.png" -msgstr "img/logo/logo_user_02_en.png" - -#: .\templates\account\base.html:67 .\templates\admin\base_site.html:14 -#: .\templates\admin\login.html:21 -msgid "注销" -msgstr "Logout" - -#: .\templates\account\base.html:82 -msgid "返回顶部" -msgstr "Back top" - -#: .\templates\account\base.html:85 -msgid "返回底部" -msgstr "Back bottom" - -#: .\templates\account\base.html:94 .\templates\account\login.html:66 -msgid "QQ咨询" -msgstr "QQ" - -#: .\templates\account\base.html:95 .\templates\account\login.html:67 -msgid "蓝鲸论坛" -msgstr "BlueKing Forum" - -#: .\templates\account\base.html:96 .\templates\account\login.html:68 -msgid "蓝鲸官网" -msgstr "Blueking Official" - -#: .\templates\account\base.html:100 -msgid "蓝鲸智云 版权所有" -msgstr " " - -#: .\templates\account\login.html:10 -msgid "登录|蓝鲸智云企业版" +#: templates/login/login.html:10 +#, fuzzy +#| msgid "登录|蓝鲸智云企业版" +msgid "登录|蓝鲸智云" msgstr "Login|BlueKing" -#: .\templates\account\login.html:16 -msgid "img/logo/bk_login.png" -msgstr "img/logo/bk_login_en.png" - -#: .\templates\account\login.html:38 +#: templates/login/login.html:22 msgid "账户或者密码错误,请重新输入" msgstr "Username or password is incorrect" -#: .\templates\account\login.html:44 +#: templates/login/login.html:28 msgid "请输入用户名" msgstr "Please enter your username" -#: .\templates\account\login.html:48 +#: templates/login/login.html:32 msgid "请输入用户密码" msgstr "Please enter your password" -#: .\templates\account\login.html:55 +#: templates/login/login.html:39 msgid "登录" msgstr "SIGN IN" -#: .\templates\account\login.html:56 +#: templates/login/login.html:40 msgid "查看用户协议" msgstr "Agreement" -#: .\templates\account\login.html:78 +#: templates/login/login.html:48 +msgid "青藤云安全提供安全检测" +msgstr "" + +#: templates/login/login.html:55 +msgid "关注我们" +msgstr "" + +#: templates/login/login.html:72 msgid "" "您的浏览器非Chrome,建议您使用最新版本的Chrome浏览,以保证最好的体验效果" msgstr "" "Your browser is not Chrome, we recommend using the latest version of Chrome " "for the best experience" -#: .\templates\account\login.html:82 -msgid "企业证书校验无效,请联系系统管理员处理" -msgstr "" -"Enterprise certificate verification ineffective, please contact the system " -"administrator" +#~ msgid "用户名[%s]不存在" +#~ msgstr "Username [%s] does not exist" -#: .\templates\account\no_right.html:5 -msgid "你不是管理员, 没有用户管理的权限!" -msgstr "" -"You are not an administrator, so you have no permissions for user management!" +#~ msgid "用户[%s]密码重置失败" +#~ msgstr "User [%s] password reset failed" -#: .\templates\account\no_right.html:6 -msgid "请找管理员申请权限!" -msgstr "Please contact administrator to apply for permissions!" +#~ msgid "email【%s】格式错误" +#~ msgstr "Email format [%s] error" -#: .\templates\account\user_role_manage_table.part:50 -msgid "没有用户配置了平台角色" -msgstr "No user has configured the platform role" +#~ msgid "用户%s不存在" +#~ msgstr "User [%s] does not exist" -#: .\templates\account\user_table.part:24 -msgid "操作" -msgstr "operation" +#~ msgid "用户导入成功" +#~ msgstr "User import succeeded" -#: .\templates\account\user_table.part:49 -#: .\templates\account\user_table.part:56 .\templates\account\users.html:30 -msgid "职能化" -msgstr "operator" +#~ msgid "您的权限不足" +#~ msgstr "Your permission is insufficient" -#: .\templates\account\user_table.part:62 -msgid "取消" -msgstr "Cancel" +#~ msgid "用户角色修改成功" +#~ msgstr "User role modification succeeded" -#: .\templates\account\user_table.part:63 .\templates\account\users.html:62 -msgid "保存" -msgstr "Save" +#~ msgid "参数错误,language和timezone不能同时为空" +#~ msgstr "" +#~ "Parameter error, language and timezone can not both be empty at the same " +#~ "time" -#: .\templates\account\user_table.part:64 -msgid "编辑" -msgstr "Edit" +#~ msgid "设置成功" +#~ msgstr "Set successfully" -#: .\templates\account\user_table.part:65 -msgid "重置密码" -msgstr "Reset Passowrd" +#~ msgid "证书文件(platform.cert)不存在: %s" +#~ msgstr "Certificate file (platform.cert) does not exist: %s" -#: .\templates\account\user_table.part:67 -msgid "删除" -msgstr "Delete" +#~ msgid "密钥文件(platform.key)不存在: %s" +#~ msgstr "Secret key file (platform.key) does not exist: %s" -#: .\templates\account\user_table.part:73 -msgid "没有数据" -msgstr "No data" +#~ msgid "证书文件(platform.cert)为空或已被损坏" +#~ msgstr "Certificate file (platform.cert) is empty or has been damaged" -#: .\templates\account\user_table.part:85 -#: .\templates\account\user_table.part:87 -msgid "上一页" -msgstr "Previous" +#~ msgid "license_server请求校验证书异常" +#~ msgstr "" +#~ "Exceptions occurred in request license server to certificate validation" -#: .\templates\account\user_table.part:109 -#: .\templates\account\user_table.part:111 -msgid "下一页" -msgstr "Next" +#~ msgid "证书不可用,请求未返回有效期或返回格式有误" +#~ msgstr "" +#~ "Certificate is not available, the request did not return a valid period " +#~ "or the return format is incorrect" -#: .\templates\account\users.html:11 -msgid "统一角色管理" -msgstr "Unified role management" +#~ msgid "证书校验成功" +#~ msgstr "Certificate validation succeeded" -#: .\templates\account\users.html:12 -msgid "导出" -msgstr "Export" +#~ msgid "企业证书无效:%s; 只影响桌面版本信息的展示" +#~ msgstr "" +#~ "Enterprise certificate is invalid: %s; it just has an impact on the " +#~ "demonstration of desktop version information " -#: .\templates\account\users.html:13 -msgid "批量导入" -msgstr "Batch import" +#~ msgid "管控平台" +#~ msgstr "Control System" -#: .\templates\account\users.html:14 -msgid "新增用户" -msgstr "Add user" +#~ msgid "作业平台" +#~ msgstr "Job System" -#: .\templates\account\users.html:16 -msgid "用户信息" -msgstr "User information" +#~ msgid "配置平台" +#~ msgstr "Configuration System" -#: .\templates\account\users.html:24 -msgid "查询:按用户名、中文名" -msgstr "search: by username, nickname" +#~ msgid "集成平台" +#~ msgstr "Integration System" -#: .\templates\account\users.html:26 -msgid "所有用户" -msgstr "All users" +#~ msgid "网络平台" +#~ msgstr "Network System" -#: .\templates\account\users.html:33 -msgid "查询" -msgstr "Search" +#~ msgid "蓝鲸监控" +#~ msgstr "BK Monitor" -#: .\templates\account\users.html:34 -msgid "新增用户的默认密码为:" -msgstr "Default password of new user is " +#~ msgid "日志检索" +#~ msgstr "Log-Search" -#: .\templates\account\users.html:39 -msgid "温馨提示:" -msgstr "Tips:" +#~ msgid "故障自愈" +#~ msgstr "Fault Auto-recovery" -#: .\templates\account\users.html:42 -msgid "" -"

管理员可以管理所有用户的信息,具有所有权限

普通" -"用户可以管理自己的用户信息和访问 “桌面”

开发者可以" -"管理自己的用户信息、访问 “桌面” 和访问 “开发者中心”

职能化用户在普通用户权限上还拥有SaaS应用 “标准运维” 的职能化权限

审计" -"员在普通用户权限上还拥有SaaS应用 “标准运维”和作业平台的审计权限

" -msgstr "" -"

Superusercan manage the information of all users, provided " -"with all permissions

Staffcan manage the user information " -"of his own and access the blueking desktop

Developercan " -"manage the user information of his own, and can access the blueking desktop " -"and developer center

Operatorowns the operation " -"permission of SaaS APP - Standard OPS, in addition the permissions of common " -"users

Auditorowns the audit permission of SaaS APP - " -"Standard OPS and Job System, in addition the permissions of common users

" +#~ msgid "标准运维" +#~ msgstr "Standard OPS" -#: .\templates\account\users.html:56 -msgid "用户信息管理" -msgstr "User information management" +#~ msgid "Agent安装" +#~ msgstr "Agent Install" -#: .\templates\account\users.html:59 -msgid "添加用户:" -msgstr "Add user: " +#~ msgid "数据平台" +#~ msgstr "Data System" -#: .\templates\account\users.html:61 -msgid "添加" -msgstr "Add" +#~ msgid "数据平台官网" +#~ msgstr "DataWeb" -#: .\templates\account\users.html:73 -msgid "选择文件:" -msgstr "Select file:" +#~ msgid "开发框架" +#~ msgstr "Python Framework" -#: .\templates\account\users.html:75 -msgid "导入用户" -msgstr "Import user" +#~ msgid "开发样例" +#~ msgstr "Python Framework demo" -#: .\templates\account\users.html:76 -msgid "提交" -msgstr "Submit" +#~ msgid "包管理" +#~ msgstr "CDMan" -#: .\templates\account\users.html:79 -msgid "bk_user_import.xls" -msgstr "bk_user_import_en.xls" +#~ msgid "审批系统" +#~ msgstr "Approval System" -#: .\templates\account\users.html:79 -msgid "点击下载EXCEL模板" -msgstr "Click to download EXCEL template" +#~ msgid "经费管理" +#~ msgstr "Funds Manage" -#: .\templates\account\users.html:83 -msgid "注意:" -msgstr "Note:" +#~ msgid "会议管理" +#~ msgstr "Meeting Manage" -#: .\templates\account\users.html:84 -#, python-format -msgid "" -"

1.请下载EXCEL模板文件填写" -"用户数据

2.用户名为必填,包含数字和字母,长度在4-20个字符" -"

3.用户名为唯一标识,重复导入会覆盖已有数据

4.导入" -"用户默认密码为:%(default_paasword)s

5.文件后缀名必须为:" -".xls.xlsx

6.导入失败请检查EXCEL格式规范," -"或重新下载模板填写

" -msgstr "" -"

1. Please download EXCEL " -"template file and fill in user data

2.Username is " -"required, including numbers and letters, the length of 4-20 characters

3.Username a unique identifier, duplicate import will " -"overwrite existing data

4. Default passowrd of imported users: " -"%(default_paasword)s

5. The file extension must be .xls or .xlsx

6. If import failed, please check the " -"EXCEL format specification, or re-download the template to fill in

" +#~ msgid "保存成功" +#~ msgstr "Save succeeded" -#: .\templates\account\users.html:99 -msgid "新密码:" -msgstr "Password: " +#~ msgid "蓝鲸智云桌面" +#~ msgstr "BlueKing Desktop" -#: .\templates\account\users.html:104 .\templates\account\users.html.py:110 -msgid "必填" -msgstr "Required" +#~ msgid "img/logo/bk_login.png" +#~ msgstr "img/logo/bk_login_en.png" -#: .\templates\account\users.html:105 -#, python-format -msgid "" -"请输入密码,长度在8-20个字符,可支持数字、字母以及%(sp_char)s,必须保证密码包" -"含大小写字母和数字 " -msgstr "" -"Please enter the password, the length of 8-20 characters, support numbers, " -"letters and %(sp_char)s, must ensure that the password contains uppercase " -"letters and numbers" +#~ msgid "企业证书校验无效,请联系系统管理员处理" +#~ msgstr "" +#~ "Enterprise certificate verification ineffective, please contact the " +#~ "system administrator" -#: .\templates\account\users.html:108 -msgid "确认密码" -msgstr "Comfirm" +#~ msgid "你不是管理员, 没有用户管理的权限!" +#~ msgstr "" +#~ "You are not an administrator, so you have no permissions for user " +#~ "management!" -#: .\templates\account\users.html:109 -msgid "再次输入密码" -msgstr "Input password again" +#~ msgid "请找管理员申请权限!" +#~ msgstr "Please contact administrator to apply for permissions!" -#: .\templates\admin\base_site.html:4 -msgid "管理" -msgstr "Management" +#~ msgid "没有用户配置了平台角色" +#~ msgstr "No user has configured the platform role" -#: .\templates\admin\base_site.html:7 -msgid "蓝鲸智云后台管理" -msgstr "BlueKing Backstage management" +#~ msgid "职能化" +#~ msgstr "operator" -#: .\templates\admin\base_site.html:12 -msgid "修改密码" -msgstr "Change Password" +#~ msgid "统一角色管理" +#~ msgstr "Unified role management" -#: .\templates\admin\login.html:7 -msgid "您暂时不能访问该站点的后台管理,这是以下原因造成的:" -msgstr "" -"You are currently not able to access the site's backend management for the " -"following reasons." +#~ msgid "用户信息管理" +#~ msgstr "User information management" -#: .\templates\admin\login.html:15 .\templates\admin\login.html.py:17 -msgid "用户" -msgstr "user" +#~ msgid "添加用户:" +#~ msgstr "Add user: " -#: .\templates\admin\login.html:15 -msgid "未激活!" -msgstr "inactivated" +#~ msgid "添加" +#~ msgstr "Add" -#: .\templates\admin\login.html:17 -msgid "没有管理员权限,请联系管理员!" -msgstr "" -" do not have administrator privileges, please contact the administrator!" +#~ msgid "管理" +#~ msgstr "Management" -#: .\templates\csrf_failure.html:6 .\templates\csrf_failure.html.py:20 -msgid "CSRF验证失败" -msgstr "CSRF verification failed" +#~ msgid "您暂时不能访问该站点的后台管理,这是以下原因造成的:" +#~ msgstr "" +#~ "You are currently not able to access the site's backend management for " +#~ "the following reasons." -#: .\templates\csrf_failure.html:22 -msgid "" -"您看到此消息是由于该站点在提交表单时需要一个CSRF cookie。此项是出于安全考虑," -"以确保您的浏览器没有被第三方劫持。" -msgstr "" -"You see this message because the site needs a CSRF cookie when submitting " -"the form. This is for security reasons to make sure your browser is not " -"hijacked by a third party." +#~ msgid "用户" +#~ msgstr "user" -#: .\templates\csrf_failure.html:23 -msgid "" -"如果您已经设置浏览器禁用cookies,请重新启用,至少针对这个站点,全部HTTPS请" -"求,或者同源请求(same-origin)启用cookies。" -msgstr "" -"If you have set your browser to disable cookies, please enable it again, " -"enabling cookies at least for this site, for all HTTPS requests, or same-" -"origin requests." +#~ msgid "未激活!" +#~ msgstr "inactivated" -#: .\templates\csrf_failure.html:24 -msgid "重新登录" -msgstr "Login again" +#~ msgid "没有管理员权限,请联系管理员!" +#~ msgstr "" +#~ " do not have administrator privileges, please contact the administrator!" #~ msgid "img/logo/login_text.png" #~ msgstr "img/logo/login_text_en.png" diff --git a/paas-ce/paas/login/locale/en/LC_MESSAGES/djangojs.po b/paas-ce/paas/login/locale/en/LC_MESSAGES/djangojs.po index 84305e94b..78b6362be 100644 --- a/paas-ce/paas/login/locale/en/LC_MESSAGES/djangojs.po +++ b/paas-ce/paas/login/locale/en/LC_MESSAGES/djangojs.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-03-26 23:34+0800\n" +"POT-Creation-Date: 2019-03-28 20:33+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,280 +17,88 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: .\static\admin\js\SelectFilter2.js:45 -#, javascript-format -msgid "Available %s" -msgstr "Available %s" - -#: .\static\admin\js\SelectFilter2.js:46 -#, javascript-format -msgid "" -"This is the list of available %s. You may choose some by selecting them in " -"the box below and then clicking the \"Choose\" arrow between the two boxes." -msgstr "" -"This is the list of available %s. You may choose some by selecting them in " -"the box below and then clicking the \"Choose\" arrow between the two boxes." - -#: .\static\admin\js\SelectFilter2.js:53 -#, javascript-format -msgid "Type into this box to filter down the list of available %s." -msgstr "Type into this box to filter down the list of available %s." - -#: .\static\admin\js\SelectFilter2.js:57 -msgid "Filter" -msgstr "Filter" - -#: .\static\admin\js\SelectFilter2.js:61 -msgid "Choose all" -msgstr "Choose all" - -#: .\static\admin\js\SelectFilter2.js:61 -#, javascript-format -msgid "Click to choose all %s at once." -msgstr "Click to choose all %s at once." - -#: .\static\admin\js\SelectFilter2.js:67 -msgid "Choose" -msgstr "Choose" - -#: .\static\admin\js\SelectFilter2.js:69 -msgid "Remove" -msgstr "Remove" - -#: .\static\admin\js\SelectFilter2.js:75 -#, javascript-format -msgid "Chosen %s" -msgstr "Chosen %s" - -#: .\static\admin\js\SelectFilter2.js:76 -#, javascript-format -msgid "" -"This is the list of chosen %s. You may remove some by selecting them in the " -"box below and then clicking the \"Remove\" arrow between the two boxes." -msgstr "" -"This is the list of chosen %s. You may remove some by selecting them in the " -"box below and then clicking the \"Remove\" arrow between the two boxes." - -#: .\static\admin\js\SelectFilter2.js:80 -msgid "Remove all" -msgstr "Remove all" - -#: .\static\admin\js\SelectFilter2.js:80 -#, javascript-format -msgid "Click to remove all chosen %s at once." -msgstr "Click to remove all chosen %s at once." - -#: .\static\admin\js\actions.js:22 .\static\admin\js\actions.min.js:1 -msgid "%(sel)s of %(cnt)s selected" -msgid_plural "%(sel)s of %(cnt)s selected" -msgstr[0] "%(sel)s of %(cnt)s selected" -msgstr[1] "%(sel)s of %(cnt)s selected" - -#: .\static\admin\js\actions.js:114 .\static\admin\js\actions.min.js:4 -msgid "" -"You have unsaved changes on individual editable fields. If you run an " -"action, your unsaved changes will be lost." -msgstr "" -"You have unsaved changes on individual editable fields. If you run an " -"action, your unsaved changes will be lost." - -#: .\static\admin\js\actions.js:126 .\static\admin\js\actions.min.js:5 -msgid "" -"You have selected an action, but you haven't saved your changes to " -"individual fields yet. Please click OK to save. You'll need to re-run the " -"action." -msgstr "" -"You have selected an action, but you haven't saved your changes to " -"individual fields yet. Please click OK to save. You'll need to re-run the " -"action." - -#: .\static\admin\js\actions.js:128 .\static\admin\js\actions.min.js:5 -msgid "" -"You have selected an action, and you haven't made any changes on individual " -"fields. You're probably looking for the Go button rather than the Save " -"button." -msgstr "" -"You have selected an action, and you haven't made any changes on individual " -"fields. You're probably looking for the Go button rather than the Save " -"button." - -#: .\static\admin\js\admin\DateTimeShortcuts.js:79 -#, javascript-format -msgid "Note: You are %s hour ahead of server time." -msgid_plural "Note: You are %s hours ahead of server time." -msgstr[0] "Note: You are %s hour ahead of server time." -msgstr[1] "Note: You are %s hours ahead of server time." - -#: .\static\admin\js\admin\DateTimeShortcuts.js:87 -#, javascript-format -msgid "Note: You are %s hour behind server time." -msgid_plural "Note: You are %s hours behind server time." -msgstr[0] "Note: You are %s hour behind server time." -msgstr[1] "Note: You are %s hours behind server time." - -#: .\static\admin\js\admin\DateTimeShortcuts.js:114 -#: .\static\admin\js\admin\DateTimeShortcuts.js:149 -msgid "Now" -msgstr "Now" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:118 -msgid "Clock" -msgstr "Clock" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:146 -msgid "Choose a time" -msgstr "Choose a time" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:150 -msgid "Midnight" -msgstr "Midnight" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:151 -msgid "6 a.m." -msgstr "6 a.m." - -#: .\static\admin\js\admin\DateTimeShortcuts.js:152 -msgid "Noon" -msgstr "Noon" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:156 -#: .\static\admin\js\admin\DateTimeShortcuts.js:276 -msgid "Cancel" -msgstr "Cancel" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:216 -#: .\static\admin\js\admin\DateTimeShortcuts.js:269 -msgid "Today" -msgstr "Today" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:220 -msgid "Calendar" -msgstr "Calendar" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:267 -msgid "Yesterday" -msgstr "Yesterday" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:271 -msgid "Tomorrow" -msgstr "Tomorrow" - -#: .\static\admin\js\calendar.js:8 -msgid "" -"January February March April May June July August September October November " -"December" -msgstr "" -"January February March April May June July August September October November " -"December" - -#: .\static\admin\js\calendar.js:9 -msgid "S M T W T F S" -msgstr "S M T W T F S" - -#: .\static\admin\js\collapse.js:8 .\static\admin\js\collapse.js:19 -#: .\static\admin\js\collapse.min.js:1 -msgid "Show" -msgstr "Show" - -#: .\static\admin\js\collapse.js:16 .\static\admin\js\collapse.min.js:1 -msgid "Hide" -msgstr "Hide" - -#: .\static\js\csrftoken.js:20 .\static\js\csrftoken.js:31 -#: .\static\js\csrftoken.min.js:1 +#: static/js/csrftoken.js:27 static/js/csrftoken.js:38 +#: static/js/csrftoken.min.js:8 msgid "提示" msgstr "Tips" -#: .\static\js\csrftoken.js:33 .\static\js\csrftoken.min.js:1 +#: static/js/csrftoken.js:40 static/js/csrftoken.min.js:8 msgid "系统出现异常:" msgstr "System has an exception, " -#: .\static\js\role_manage.js:3 .\static\js\role_manage.js:11 -#: .\static\js\role_manage.min.js:1 -msgid "输入用户名" -msgstr "Enter username" - -#: .\static\js\role_manage.js:26 .\static\js\role_manage.min.js:1 -msgid "用户(" -msgstr "User(" - -#: .\static\js\role_manage.js:26 .\static\js\role_manage.min.js:1 -msgid ")已存在" -msgstr ") already exists" - -#: .\static\js\users.js:13 .\static\js\users.min.js:1 +#: static/js/users.js:20 static/js/users.min.js:8 msgid "不可同时修改多个用户信息,请先保存编辑中的用户信息" msgstr "" "You cannot modify the information of multiple users at the same time. Please " "save the edited user information first" -#: .\static\js\users.js:44 .\static\js\users.js:220 .\static\js\users.min.js:1 +#: static/js/users.js:51 static/js/users.js:206 static/js/users.min.js:8 msgid "请输入用户名" msgstr "Enter username" -#: .\static\js\users.js:47 .\static\js\users.min.js:1 +#: static/js/users.js:54 static/js/users.min.js:8 msgid "请输入姓名" msgstr "Enter nickname" -#: .\static\js\users.js:50 .\static\js\users.min.js:1 +#: static/js/users.js:57 static/js/users.min.js:8 msgid "请输入联系电话" msgstr "Enter phone number" -#: .\static\js\users.js:53 .\static\js\users.js:223 .\static\js\users.min.js:1 +#: static/js/users.js:60 static/js/users.js:209 static/js/users.min.js:8 msgid "请输入邮箱" msgstr "Enter email address" -#: .\static\js\users.js:57 .\static\js\users.min.js:1 +#: static/js/users.js:64 static/js/users.min.js:8 msgid "普通用户" msgstr "staff" -#: .\static\js\users.js:58 .\static\js\users.min.js:1 +#: static/js/users.js:65 static/js/users.min.js:8 msgid "管理员" msgstr "superuser" -#: .\static\js\users.js:59 .\static\js\users.min.js:1 +#: static/js/users.js:66 static/js/users.min.js:8 msgid "开发者" msgstr "developer" -#: .\static\js\users.js:60 .\static\js\users.min.js:1 -msgid "职能化" +#: static/js/users.js:67 static/js/users.min.js:8 +msgid "职能化用户" msgstr "operator" -#: .\static\js\users.js:61 .\static\js\users.min.js:1 +#: static/js/users.js:68 static/js/users.min.js:8 msgid "审计员" msgstr "auditor" -#: .\static\js\users.js:65 .\static\js\users.js:309 .\static\js\users.js:328 -#: .\static\js\users.min.js:1 +#: static/js/users.js:72 static/js/users.js:296 static/js/users.js:315 +#: static/js/users.min.js:8 msgid "取消" msgstr "Cancel" -#: .\static\js\users.js:66 .\static\js\users.min.js:1 +#: static/js/users.js:73 static/js/users.min.js:8 msgid "保存" msgstr "Save" -#: .\static\js\users.js:67 .\static\js\users.min.js:1 +#: static/js/users.js:74 static/js/users.min.js:8 msgid "编辑" msgstr "Edit" -#: .\static\js\users.js:68 .\static\js\users.min.js:1 +#: static/js/users.js:75 static/js/users.min.js:8 msgid "删除" msgstr "Delete" -#: .\static\js\users.js:69 .\static\js\users.js:324 .\static\js\users.js:331 -#: .\static\js\users.min.js:1 +#: static/js/users.js:76 static/js/users.js:311 static/js/users.js:318 +#: static/js/users.min.js:8 msgid "重置密码" msgstr "Reset password" -#: .\static\js\users.js:88 .\static\js\users.min.js:1 +#: static/js/users.js:95 static/js/users.min.js:8 msgid "批量导入用户" msgstr "Import users in batch" -#: .\static\js\users.js:101 .\static\js\users.min.js:1 +#: static/js/users.js:108 static/js/users.min.js:8 msgid "请选择一个文件" msgstr "Please choose a file" -#: .\static\js\users.js:116 .\static\js\users.min.js:1 +#: static/js/users.js:123 static/js/users.min.js:8 #, fuzzy #| msgid "" #| "用户名只能包含数字、字母和点,且长度在4-20个字符, 且必须以字母或数字开头" @@ -301,72 +109,216 @@ msgstr "" "Username can only contain numbers, letters and dots, and the length is " "between 4-20 characters and must start with letters or number" -#: .\static\js\users.js:121 .\static\js\users.min.js:1 +#: static/js/users.js:128 static/js/users.min.js:8 msgid "中文名只能包含数字、字母、中文汉字、下划线,长度在1-16个字符" msgstr "" "Nickname can only contain numbers, letters and underscores, with a length of " "1-16 characters" -#: .\static\js\users.js:126 .\static\js\users.min.js:1 +#: static/js/users.js:133 static/js/users.min.js:8 msgid "仅支持中国大陆手机号码(11位数字)" msgstr "Only support 10-digit phone number " -#: .\static\js\users.js:131 .\static\js\users.min.js:1 +#: static/js/users.js:138 static/js/users.min.js:8 msgid "请输入正确的邮箱格式" msgstr "Please enter correct format of email address" -#: .\static\js\users.js:136 .\static\js\users.min.js:1 +#: static/js/users.js:143 static/js/users.min.js:8 msgid "请选择角色" msgstr "Please choose a role" -#: .\static\js\users.js:155 .\static\js\users.min.js:1 +#: static/js/users.js:157 static/js/users.min.js:8 msgid "保存成功" msgstr "Save succeeded" -#: .\static\js\users.js:165 .\static\js\users.min.js:1 -msgid "保存失败" -msgstr "Save failed" - -#: .\static\js\users.js:183 .\static\js\users.min.js:1 +#: static/js/users.js:174 static/js/users.min.js:8 msgid "添加成功" msgstr "Add succeeded" -#: .\static\js\users.js:196 .\static\js\users.min.js:1 -msgid "添加失败" -msgstr "Add failed" - -#: .\static\js\users.js:221 .\static\js\users.min.js:1 +#: static/js/users.js:207 static/js/users.min.js:8 msgid "请输入中文名" msgstr "Please enter your nickname" -#: .\static\js\users.js:222 .\static\js\users.min.js:1 +#: static/js/users.js:208 static/js/users.min.js:8 msgid "请输入手机号" msgstr "Please enter your phone number " -#: .\static\js\users.js:282 .\static\js\users.min.js:1 +#: static/js/users.js:268 static/js/users.min.js:8 msgid "您确定删除该用户吗?" msgstr "Are you sure you want to delete this user?" -#: .\static\js\users.js:282 .\static\js\users.min.js:1 +#: static/js/users.js:268 static/js/users.min.js:8 msgid "用户名 : " msgstr "Username: " -#: .\static\js\users.js:285 .\static\js\users.min.js:1 +#: static/js/users.js:271 static/js/users.min.js:8 msgid "删除确认" msgstr "Delete confirmation" -#: .\static\js\users.js:291 .\static\js\users.min.js:1 +#: static/js/users.js:277 static/js/users.min.js:8 msgid "正在进行删除操作,请稍后..." msgstr "In deleting, please wait" -#: .\static\js\users.js:308 .\static\js\users.min.js:1 +#: static/js/users.js:295 static/js/users.min.js:8 msgid "确认删除" msgstr "Confirm delete" -#: .\static\js\users.js:358 .\static\js\users.min.js:1 +#: static/js/users.js:345 static/js/users.min.js:8 msgid "两次输入的新密码不一致" msgstr "Two passwords entered in twice are not the same" -#: .\static\js\users.js:389 .\static\js\users.min.js:1 +#: static/js/users.js:370 static/js/users.min.js:8 msgid "密码重置成功" msgstr "Password reset succeeded" + +#~ msgid "Available %s" +#~ msgstr "Available %s" + +#~ msgid "" +#~ "This is the list of available %s. You may choose some by selecting them " +#~ "in the box below and then clicking the \"Choose\" arrow between the two " +#~ "boxes." +#~ msgstr "" +#~ "This is the list of available %s. You may choose some by selecting them " +#~ "in the box below and then clicking the \"Choose\" arrow between the two " +#~ "boxes." + +#~ msgid "Type into this box to filter down the list of available %s." +#~ msgstr "Type into this box to filter down the list of available %s." + +#~ msgid "Filter" +#~ msgstr "Filter" + +#~ msgid "Choose all" +#~ msgstr "Choose all" + +#~ msgid "Click to choose all %s at once." +#~ msgstr "Click to choose all %s at once." + +#~ msgid "Choose" +#~ msgstr "Choose" + +#~ msgid "Remove" +#~ msgstr "Remove" + +#~ msgid "Chosen %s" +#~ msgstr "Chosen %s" + +#~ msgid "" +#~ "This is the list of chosen %s. You may remove some by selecting them in " +#~ "the box below and then clicking the \"Remove\" arrow between the two " +#~ "boxes." +#~ msgstr "" +#~ "This is the list of chosen %s. You may remove some by selecting them in " +#~ "the box below and then clicking the \"Remove\" arrow between the two " +#~ "boxes." + +#~ msgid "Remove all" +#~ msgstr "Remove all" + +#~ msgid "Click to remove all chosen %s at once." +#~ msgstr "Click to remove all chosen %s at once." + +#~ msgid "%(sel)s of %(cnt)s selected" +#~ msgid_plural "%(sel)s of %(cnt)s selected" +#~ msgstr[0] "%(sel)s of %(cnt)s selected" +#~ msgstr[1] "%(sel)s of %(cnt)s selected" + +#~ msgid "" +#~ "You have unsaved changes on individual editable fields. If you run an " +#~ "action, your unsaved changes will be lost." +#~ msgstr "" +#~ "You have unsaved changes on individual editable fields. If you run an " +#~ "action, your unsaved changes will be lost." + +#~ msgid "" +#~ "You have selected an action, but you haven't saved your changes to " +#~ "individual fields yet. Please click OK to save. You'll need to re-run the " +#~ "action." +#~ msgstr "" +#~ "You have selected an action, but you haven't saved your changes to " +#~ "individual fields yet. Please click OK to save. You'll need to re-run the " +#~ "action." + +#~ msgid "" +#~ "You have selected an action, and you haven't made any changes on " +#~ "individual fields. You're probably looking for the Go button rather than " +#~ "the Save button." +#~ msgstr "" +#~ "You have selected an action, and you haven't made any changes on " +#~ "individual fields. You're probably looking for the Go button rather than " +#~ "the Save button." + +#~ msgid "Note: You are %s hour ahead of server time." +#~ msgid_plural "Note: You are %s hours ahead of server time." +#~ msgstr[0] "Note: You are %s hour ahead of server time." +#~ msgstr[1] "Note: You are %s hours ahead of server time." + +#~ msgid "Note: You are %s hour behind server time." +#~ msgid_plural "Note: You are %s hours behind server time." +#~ msgstr[0] "Note: You are %s hour behind server time." +#~ msgstr[1] "Note: You are %s hours behind server time." + +#~ msgid "Now" +#~ msgstr "Now" + +#~ msgid "Clock" +#~ msgstr "Clock" + +#~ msgid "Choose a time" +#~ msgstr "Choose a time" + +#~ msgid "Midnight" +#~ msgstr "Midnight" + +#~ msgid "6 a.m." +#~ msgstr "6 a.m." + +#~ msgid "Noon" +#~ msgstr "Noon" + +#~ msgid "Cancel" +#~ msgstr "Cancel" + +#~ msgid "Today" +#~ msgstr "Today" + +#~ msgid "Calendar" +#~ msgstr "Calendar" + +#~ msgid "Yesterday" +#~ msgstr "Yesterday" + +#~ msgid "Tomorrow" +#~ msgstr "Tomorrow" + +#~ msgid "" +#~ "January February March April May June July August September October " +#~ "November December" +#~ msgstr "" +#~ "January February March April May June July August September October " +#~ "November December" + +#~ msgid "S M T W T F S" +#~ msgstr "S M T W T F S" + +#~ msgid "Show" +#~ msgstr "Show" + +#~ msgid "Hide" +#~ msgstr "Hide" + +#~ msgid "输入用户名" +#~ msgstr "Enter username" + +#~ msgid "用户(" +#~ msgstr "User(" + +#~ msgid ")已存在" +#~ msgstr ") already exists" + +#~ msgid "保存失败" +#~ msgstr "Save failed" + +#~ msgid "添加失败" +#~ msgstr "Add failed" diff --git a/paas-ce/paas/login/locale/zh_Hans/LC_MESSAGES/django.po b/paas-ce/paas/login/locale/zh_Hans/LC_MESSAGES/django.po index 0e747ea05..d24df3cde 100644 --- a/paas-ce/paas/login/locale/zh_Hans/LC_MESSAGES/django.po +++ b/paas-ce/paas/login/locale/zh_Hans/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-03-26 23:33+0800\n" +"POT-Creation-Date: 2019-03-28 20:33+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,524 +18,605 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: .\bkaccount\accounts.py:125 +#: bkaccount/accounts.py:127 msgid "缺少参数bk_token" msgstr "" -#: .\bkaccount\accounts.py:135 +#: bkaccount/accounts.py:136 msgid "参数bk_token非法" msgstr "" -#: .\bkaccount\accounts.py:146 -#, python-format -msgid "不存在bk_token[%s]的记录" +#: bkaccount/accounts.py:152 +msgid "不存在该bk_token的记录" msgstr "" -#: .\bkaccount\accounts.py:153 +#: bkaccount/accounts.py:159 msgid "登录态已注销" msgstr "" -#: .\bkaccount\accounts.py:157 +#: bkaccount/accounts.py:163 msgid "登录态已过期" msgstr "" -#: .\bkaccount\accounts.py:161 +#: bkaccount/accounts.py:167 msgid "登录态有效期不合法" msgstr "" -#: .\bkaccount\admin.py:20 -msgid "Personal info" +#: bkaccount/constants.py:37 templates/bkaccount/user_table.part:46 +#: templates/bkaccount/user_table.part:54 templates/bkaccount/users.html:27 +msgid "普通用户" msgstr "" -#: .\bkaccount\admin.py:21 -msgid "Contact info" +#: bkaccount/constants.py:38 templates/bkaccount/user_table.part:47 +#: templates/bkaccount/users.html:26 +msgid "管理员" msgstr "" -#: .\bkaccount\admin.py:22 -msgid "Permissions" +#: bkaccount/constants.py:39 templates/bkaccount/user_table.part:48 +#: templates/bkaccount/user_table.part:55 templates/bkaccount/users.html:28 +msgid "开发者" msgstr "" -#: .\bkaccount\admin.py:23 -msgid "Important dates" +#: bkaccount/constants.py:40 templates/bkaccount/user_table.part:49 +#: templates/bkaccount/user_table.part:56 templates/bkaccount/users.html:29 +msgid "职能化用户" msgstr "" -#: .\bkaccount\constants.py:33 .\templates\account\user_table.part:46 -#: .\templates\account\user_table.part:54 .\templates\account\users.html:28 -msgid "普通用户" +#: bkaccount/constants.py:41 templates/bkaccount/user_table.part:50 +#: templates/bkaccount/user_table.part:57 templates/bkaccount/users.html:30 +msgid "审计员" msgstr "" -#: .\bkaccount\constants.py:34 -msgid "超级管理员" +#: bkaccount/constants.py:75 +msgid "中文" msgstr "" -#: .\bkaccount\constants.py:35 .\templates\account\user_table.part:48 -#: .\templates\account\user_table.part:55 .\templates\account\users.html:29 -msgid "开发者" +#: bkaccount/constants.py:76 +msgid "英文" msgstr "" -#: .\bkaccount\constants.py:36 -msgid "职能化用户" +#: bkaccount/forms.py:70 +msgid "名称长度不能超过16个字符" msgstr "" -#: .\bkaccount\constants.py:37 .\templates\account\user_table.part:50 -#: .\templates\account\user_table.part:57 .\templates\account\users.html:31 -msgid "审计员" +#: bkaccount/forms.py:73 +msgid "手机号长度不能超过11个字符" msgstr "" -#: .\bkaccount\constants.py:71 -msgid "中文" +#: bkaccount/forms.py:81 +msgid "中文名错误,只能包含数字、字母、中文汉字、下划线,长度在1-16个字符" msgstr "" -#: .\bkaccount\constants.py:72 -msgid "英文" +#: bkaccount/forms.py:88 +msgid "手机号错误,仅支持11位数字的号码" msgstr "" -#: .\bkaccount\manager.py:52 -#, python-format -msgid "用户名[%s]不存在" +#: bkaccount/forms.py:94 +msgid "用户名不能为空" msgstr "" -#: .\bkaccount\manager.py:149 -#, python-format -msgid "用户[%s]密码重置失败" +#: bkaccount/forms.py:95 +msgid "用户名长度不能超过20个字符" msgstr "" -#: .\bkaccount\manager.py:167 -#, python-format -msgid "个人[%s]信息修改失败" +#: bkaccount/forms.py:96 +msgid "用户名长度不能少于4个字符" msgstr "" -#: .\bkaccount\manager.py:194 .\bkaccount\manager.py:235 -#, python-format -msgid "账号为:%s 的用户是最后一个管理员,不可修改其角色" +#: bkaccount/forms.py:104 +msgid "" +"用户名错误,只能包含数字、字母、下划线和点,长度在4-20个字符,且必须以字母或" +"数字开头" msgstr "" -#: .\bkaccount\manager.py:260 -#, python-format -msgid "账号为:%s 的用户已经存在" +#: bkaccount/forms.py:110 bkaccount/forms.py:122 bkaccount/forms.py:132 +msgid "新密码不能为空" msgstr "" -#: .\bkaccount\manager.py:263 -#, python-format -msgid "保存用户信息(%s)出错" +#: bkaccount/forms.py:111 bkaccount/forms.py:133 +msgid "密码长度不能超过20个字符" msgstr "" -#: .\bkaccount\manager.py:296 -msgid "内置admin用户不可删除" +#: bkaccount/forms.py:112 bkaccount/forms.py:134 +msgid "密码长度不能少于8个字符" msgstr "" -#: .\bkaccount\manager.py:299 -msgid "最后一个管理员用户,不允许删除" +#: bkaccount/forms.py:124 +msgid "两次输入的新密码不一致" msgstr "" -#: .\bkaccount\manager.py:304 -#, python-format -msgid "用户(%s)删除失败" +#: bkaccount/forms.py:126 bkaccount/forms.py:141 +msgid "" +"密码只支持数字、字母或!@#$%^*()_-+=,长度在8-20个字符,且必须保证包含大小写字" +"母和数字" +msgstr "" + +#: bkaccount/forms.py:146 +msgid "wx_userid 不能为空" +msgstr "" + +#: bkaccount/forms.py:150 +msgid "文件必须上传" +msgstr "" + +#: bkaccount/forms.py:157 +msgid "批量导入用户,解析文件名出错" +msgstr "" + +#: bkaccount/forms.py:159 +msgid "文件格式错误,只支持:.xls 和 .xlsx 文件" +msgstr "" + +#: bkaccount/manager.py:61 +msgid "用户名不存在" msgstr "" -#: .\bkaccount\manager.py:318 +#: bkaccount/manager.py:159 bkaccount/manager.py:325 msgid "用户密码重置失败" msgstr "" -#: .\bkaccount\manager.py:328 +#: bkaccount/manager.py:176 +msgid "个人信息修改失败" +msgstr "" + +#: bkaccount/manager.py:201 +msgid "该用户是最后一个管理员,不可修改其角色" +msgstr "" + +#: bkaccount/manager.py:242 +msgid "用户是最后一个管理员,不可修改其角色" +msgstr "" + +#: bkaccount/manager.py:267 +msgid "用户已经存在" +msgstr "" + +#: bkaccount/manager.py:270 +msgid "保存用户信息出错" +msgstr "" + +#: bkaccount/manager.py:303 +msgid "内置admin用户不可删除" +msgstr "" + +#: bkaccount/manager.py:306 +msgid "最后一个管理员用户,不允许删除" +msgstr "" + +#: bkaccount/manager.py:311 +msgid "用户删除失败" +msgstr "" + +#: bkaccount/manager.py:335 msgid "已经绑定了微信,请解绑后再重新绑定!" msgstr "" -#: .\bkaccount\manager.py:332 +#: bkaccount/manager.py:339 msgid "该微信号已经被绑定过了" msgstr "" -#: .\bkaccount\manager.py:339 +#: bkaccount/manager.py:346 msgid "绑定用户微信信息失败" msgstr "" -#: .\bkaccount\manager.py:350 +#: bkaccount/manager.py:357 msgid "账号未绑定过微信号,无法解绑" msgstr "" -#: .\bkaccount\manager.py:354 +#: bkaccount/manager.py:361 msgid "解绑用户微信信息失败" msgstr "" -#: .\bkaccount\manager.py:385 +#: bkaccount/manager.py:392 msgid "记录成功" msgstr "" -#: .\bkaccount\manager.py:387 +#: bkaccount/manager.py:394 msgid "用户登录记录失败" msgstr "" -#: .\bkaccount\models.py:43 +#: bkaccount/models.py:51 msgid "date joined" msgstr "" -#: .\bkaccount\models.py:51 +#: bkaccount/models.py:59 msgid "user" msgstr "" -#: .\bkaccount\models.py:52 +#: bkaccount/models.py:60 msgid "users" msgstr "" -#: .\bkaccount\models.py:123 +#: bkaccount/models.py:125 msgid "create_time" msgstr "" -#: .\bkaccount\utils.py:83 -#, python-format -msgid "导出数据出现错误:%s" +#: bkaccount/utils.py:36 +msgid "用户不存在" msgstr "" -#: .\bkaccount\validators.py:16 -#, python-format -msgid "" -"用户名【%s】错误,只能包含数字、字母、下划线和点,长度在4-20个字符,且必须以" -"字母或数字开头" +#: bkaccount/utils.py:96 +msgid "导出数据出现错误" msgstr "" -#: .\bkaccount\validators.py:25 -#, python-format -msgid "" -"中文名【%s】错误,只能包含数字、字母、中文汉字、下划线,长度在1-16个字符" +#: bkaccount/views.py:147 +msgid "保存用户信息成功" msgstr "" -#: .\bkaccount\validators.py:34 -#, python-format -msgid "手机号【%s】错误,仅支持中国大陆手机号码(11位数字)" +#: bkaccount/views.py:159 +msgid "用户删除成功" msgstr "" -#: .\bkaccount\validators.py:43 -#, python-format -msgid "email【%s】格式错误" +#: bkaccount/views.py:175 +msgid "修改密码成功" msgstr "" -#: .\bkaccount\validators.py:52 -msgid "" -"密码只支持数字、字母或!@#$%^*()_-+=,长度在8-20个字符,且必须保证包含大小写字" -"母和数字" +#: bkaccount/views.py:183 common/mixins/base.py:31 common/mixins/base.py:45 +msgid "非管理员, 没有权限进行操作, 请找管理员申请权限!" msgstr "" -#: .\bkaccount\validators.py:61 -msgid "密码不能为空" +#: bkaccount/views.py:196 +msgid "文件解析出错,请下载 EXCEL模板文件 填写用户数据" msgstr "" -#: .\bkaccount\validators.py:63 -msgid "两次输入的新密码不一致" +#: bkaccount/views.py:199 +msgid "导入数据不能为空" msgstr "" -#: .\bkaccount\validators.py:80 -#, python-format -msgid "用户%s不存在" +#: bkaccount/views.py:219 +msgid "用户导入出现异常 {}" msgstr "" -#: .\bkaccount\validators.py:99 -#, python-format -msgid "批量导入用户,解析文件名出错:%s" +#: bkaccount/views.py:230 templates/bkaccount/user_table.part:19 +msgid "用户名" msgstr "" -#: .\bkaccount\validators.py:102 -msgid "文件格式错误,只支持:.xls 和 .xlsx 文件" +#: bkaccount/views.py:230 templates/bkaccount/user_table.part:20 +msgid "中文名" msgstr "" -#: .\bkaccount\views.py:115 .\bkaccount\views.py:142 .\bkaccount\views.py:161 -#: .\bkaccount\views.py:189 .\role_manage\views.py:56 -msgid "非管理员用户, 没有权限进行操作, 请找管理员申请权限!" +#: bkaccount/views.py:230 templates/bkaccount/user_table.part:21 +msgid "联系电话" msgstr "" -#: .\bkaccount\views.py:131 -msgid "保存用户信息成功" +#: bkaccount/views.py:230 templates/bkaccount/user_table.part:22 +msgid "常用邮箱" msgstr "" -#: .\bkaccount\views.py:150 -#, python-format -msgid "用户(%s)删除成功" +#: bkaccount/views.py:230 templates/bkaccount/user_table.part:23 +msgid "角色" msgstr "" -#: .\bkaccount\views.py:203 -msgid "文件解析出错,请下载 EXCEL模板文件 填写用户数据" +#: bkaccount/views_api.py:31 bkaccount/views_api_v2.py:29 +msgid "用户验证成功" msgstr "" -#: .\bkaccount\views.py:207 -msgid "导入数据为空" +#: bkaccount/views_api.py:52 bkaccount/views_api.py:69 +#: bkaccount/views_api.py:92 bkaccount/views_api_v2.py:50 +#: bkaccount/views_api_v2.py:67 bkaccount/views_api_v2.py:90 +msgid "用户信息获取成功" msgstr "" -#: .\bkaccount\views.py:240 -#, python-format -msgid "用户导入出现异常%s" +#: bkaccount/views_api.py:77 bkaccount/views_api.py:100 +#: bkaccount/views_api.py:121 bkaccount/views_api.py:144 +#: bkaccount/views_api_v2.py:75 +msgid "请求参数格式错误,必须为json格式" msgstr "" -#: .\bkaccount\views.py:242 -msgid "用户导入成功" +#: bkaccount/views_api.py:88 +msgid "缺少参数:username_list" msgstr "" -#: .\bkaccount\views.py:258 .\templates\account\user_role_manage_table.part:26 -#: .\templates\account\user_table.part:19 -msgid "用户名" +#: bkaccount/views_api.py:113 +msgid "密码重置成功" msgstr "" -#: .\bkaccount\views.py:258 .\templates\account\user_table.part:20 -msgid "中文名" +#: bkaccount/views_api.py:136 +msgid "用户信息修改成功" msgstr "" -#: .\bkaccount\views.py:258 .\templates\account\user_table.part:21 -msgid "联系电话" +#: bkaccount/views_api.py:157 +msgid "绑定成功" msgstr "" -#: .\bkaccount\views.py:258 .\templates\account\user_table.part:22 -msgid "常用邮箱" +#: bkaccount/views_api.py:165 +msgid "解绑成功" msgstr "" -#: .\bkaccount\views.py:258 .\templates\account\user_table.part:23 -msgid "角色" +#: bkaccount/views_api_v2.py:86 +msgid "缺少参数:bk_username_list" msgstr "" -#: .\bkaccount\views_api.py:26 .\bkaccount\views_api_v2.py:29 -msgid "用户验证成功" +#: conf/default.py:183 +msgid "English" msgstr "" -#: .\bkaccount\views_api.py:50 .\bkaccount\views_api.py:70 -#: .\bkaccount\views_api.py:99 .\bkaccount\views_api_v2.py:54 -#: .\bkaccount\views_api_v2.py:75 .\bkaccount\views_api_v2.py:105 -#: .\role_manage\views_api.py:40 .\role_manage\views_api_v2.py:42 -msgid "用户信息获取成功" +#: conf/default.py:184 +msgid "简体中文" msgstr "" -#: .\bkaccount\views_api.py:84 .\bkaccount\views_api.py:112 -#: .\bkaccount\views_api.py:150 .\bkaccount\views_api.py:191 -#: .\bkaccount\views_api.py:224 .\bkaccount\views_api.py:254 -#: .\bkaccount\views_api.py:279 .\bkaccount\views_api_v2.py:90 -#: .\role_manage\views_api.py:25 .\role_manage\views_api_v2.py:27 -msgid "请求参数格式错误,必须为json格式" +#: healthz/views.py:44 +msgid "配置文件不正确, 缺失对应配置: {}" msgstr "" -#: .\bkaccount\views_api.py:95 .\role_manage\views_api.py:36 -msgid "缺少参数:username_list" +#: healthz/views.py:54 +msgid "数据库连接存在问题: {}" msgstr "" -#: .\bkaccount\views_api.py:123 .\bkaccount\views_api.py:161 -#: .\bkaccount\views_api.py:201 -msgid "您的权限不足" +#: templates/401.html:6 +msgid "未登录蓝鲸智云平台(401页)" msgstr "" -#: .\bkaccount\views_api.py:137 -msgid "密码重置成功" +#: templates/401.html:20 +msgid "您需要登录蓝鲸智云" msgstr "" -#: .\bkaccount\views_api.py:178 -msgid "用户信息修改成功" +#: templates/401.html:21 +msgid "立即登录" msgstr "" -#: .\bkaccount\views_api.py:211 -msgid "用户角色修改成功" +#: templates/403.html:6 +msgid "您没有访问权限(403页)" msgstr "" -#: .\bkaccount\views_api.py:234 -msgid "参数错误,wx_userid 不能为空" +#: templates/403.html:20 +msgid "您没有访问权限,请联系系统管理员添加" msgstr "" -#: .\bkaccount\views_api.py:241 -msgid "绑定成功" +#: templates/404.html:6 +msgid "页面找不到(404页)" msgstr "" -#: .\bkaccount\views_api.py:266 -msgid "解绑成功" +#: templates/404.html:20 +msgid "页面找不到了" msgstr "" -#: .\bkaccount\views_api.py:290 -msgid "参数错误,language和timezone不能同时为空" +#: templates/500.html:6 +msgid "系统异常(500页)" msgstr "" -#: .\bkaccount\views_api.py:293 -msgid "设置成功" +#: templates/500.html:20 +msgid "系统出现异常" msgstr "" -#: .\bkaccount\views_api_v2.py:101 .\role_manage\views_api_v2.py:38 -msgid "缺少参数:bk_username_list" +#: templates/500.html:21 +msgid "努力恢复中,请稍后再试......" msgstr "" -#: .\common\license_utils.py:28 -#, python-format -msgid "证书文件(platform.cert)不存在: %s" +#: templates/50x.html:6 templates/50x.html.py:19 +msgid "服务故障,努力修复中..." msgstr "" -#: .\common\license_utils.py:31 -#, python-format -msgid "密钥文件(platform.key)不存在: %s" +#: templates/50x.html:20 +msgid "服务出现故障,我们正在紧急修复,给您带来不便,敬请谅解。" msgstr "" -#: .\common\license_utils.py:39 -msgid "证书文件(platform.cert)为空或已被损坏" +#: templates/bkaccount/base.html:11 +msgid "用户管理|蓝鲸智云社区版" msgstr "" -#: .\common\license_utils.py:55 -msgid "license_server请求校验证书异常" +#: templates/bkaccount/base.html:12 +msgid "" +"开发者中心,游戏运维,运维,服务器管理,模块配置,监控,腾讯游戏,蓝鲸,智云,devops," +"运维开发,蓝鲸社区版,社区版,作业平台,集成平台,配置平台,管控平台" msgstr "" -#: .\common\license_utils.py:108 -msgid "证书不可用,请求未返回有效期或返回格式有误" +#: templates/bkaccount/base.html:13 +msgid "" +"蓝鲸智云软件社区版是由蓝鲸智云团队提供的一套基于PaaS的技术解决方案,旨在改变" +"中国运维行业,帮助企业快速达到基础运维支撑能力,并提升技术人员的DevOps能力。" +"该版本提供了配置平台,作业平台,集成平台等强大功能,用户在使用时,请查阅并遵" +"守《蓝鲸智云软件用户服务协议》。" msgstr "" -#: .\common\license_utils.py:109 -msgid "证书校验成功" +#: templates/bkaccount/base.html:43 templates/bkaccount/base.html.py:98 +#: templates/login/login.html:54 +msgid "蓝鲸智云工作台" msgstr "" -#: .\conf\default.py:182 -msgid "English" +#: templates/bkaccount/base.html:44 +msgid "img/logo/logo_user_01.png" msgstr "" -#: .\conf\default.py:183 -msgid "简体中文" +#: templates/bkaccount/base.html:46 +msgid "蓝鲸智云用户管理" msgstr "" -#: .\healthz\views.py:67 -#, python-format -msgid "配置文件不正确, 缺失对应配置: %s" +#: templates/bkaccount/base.html:47 +msgid "img/logo/logo_user_02.png" msgstr "" -#: .\healthz\views.py:78 -#, python-format -msgid "数据库连接存在问题: %s" +#: templates/bkaccount/base.html:68 +msgid "注销" msgstr "" -#: .\healthz\views.py:87 -#, python-format -msgid "企业证书无效:%s; 只影响桌面版本信息的展示" +#: templates/bkaccount/base.html:83 +msgid "返回顶部" msgstr "" -#: .\role_manage\constants.py:6 -msgid "管控平台" +#: templates/bkaccount/base.html:86 +msgid "返回底部" msgstr "" -#: .\role_manage\constants.py:7 -msgid "作业平台" +#: templates/bkaccount/base.html:95 templates/login/login.html:51 +msgid "QQ咨询" msgstr "" -#: .\role_manage\constants.py:8 -msgid "配置平台" +#: templates/bkaccount/base.html:96 templates/login/login.html:52 +msgid "蓝鲸论坛" msgstr "" -#: .\role_manage\constants.py:9 -msgid "集成平台" +#: templates/bkaccount/base.html:97 templates/login/login.html:53 +msgid "蓝鲸官网" msgstr "" -#: .\role_manage\constants.py:10 -msgid "网络平台" +#: templates/bkaccount/base.html:101 +msgid "蓝鲸智云 版权所有" msgstr "" -#: .\role_manage\constants.py:11 -msgid "蓝鲸监控" +#: templates/bkaccount/user_table.part:24 +msgid "操作" msgstr "" -#: .\role_manage\constants.py:12 -msgid "日志检索" +#: templates/bkaccount/user_table.part:62 +msgid "取消" msgstr "" -#: .\role_manage\constants.py:13 -msgid "故障自愈" +#: templates/bkaccount/user_table.part:63 +msgid "保存" msgstr "" -#: .\role_manage\constants.py:14 -msgid "标准运维" +#: templates/bkaccount/user_table.part:64 +msgid "编辑" msgstr "" -#: .\role_manage\constants.py:15 -msgid "Agent安装" +#: templates/bkaccount/user_table.part:65 +msgid "重置密码" msgstr "" -#: .\role_manage\constants.py:16 -msgid "数据平台" +#: templates/bkaccount/user_table.part:67 +msgid "删除" msgstr "" -#: .\role_manage\constants.py:17 -msgid "数据平台官网" +#: templates/bkaccount/user_table.part:73 +msgid "没有数据" msgstr "" -#: .\role_manage\constants.py:18 -msgid "开发框架" +#: templates/bkaccount/user_table.part:85 +#: templates/bkaccount/user_table.part:87 +msgid "上一页" msgstr "" -#: .\role_manage\constants.py:19 -msgid "开发样例" +#: templates/bkaccount/user_table.part:109 +#: templates/bkaccount/user_table.part:111 +msgid "下一页" msgstr "" -#: .\role_manage\constants.py:20 -msgid "包管理" +#: templates/bkaccount/users.html:11 +msgid "导出" msgstr "" -#: .\role_manage\constants.py:21 -msgid "审批系统" +#: templates/bkaccount/users.html:12 +msgid "批量导入" msgstr "" -#: .\role_manage\constants.py:22 -msgid "经费管理" +#: templates/bkaccount/users.html:13 +msgid "新增用户" msgstr "" -#: .\role_manage\constants.py:23 -msgid "会议管理" +#: templates/bkaccount/users.html:15 +msgid "用户信息" msgstr "" -#: .\role_manage\constants.py:27 .\templates\account\user_table.part:47 -#: .\templates\account\users.html:27 -msgid "管理员" +#: templates/bkaccount/users.html:23 +msgid "查询:按用户名、中文名" msgstr "" -#: .\role_manage\constants.py:28 -msgid "操作员" +#: templates/bkaccount/users.html:25 +msgid "所有用户" msgstr "" -#: .\role_manage\views.py:63 -msgid "保存成功" +#: templates/bkaccount/users.html:32 +msgid "查询" msgstr "" -#: .\templates\401.html:6 -msgid "未登录蓝鲸智云平台(401页)" +#: templates/bkaccount/users.html:33 +msgid "新增用户的默认密码为:" msgstr "" -#: .\templates\401.html:20 -msgid "您需要登录蓝鲸智云" +#: templates/bkaccount/users.html:38 +msgid "温馨提示:" msgstr "" -#: .\templates\401.html:21 -msgid "立即登录" +#: templates/bkaccount/users.html:41 +msgid "" +"

管理员可以管理所有用户的信息,具有所有权限

普通" +"用户可以管理自己的用户信息和访问 “工作台”

开发者可" +"以管理自己的用户信息、访问 “工作台” 和访问 “开发者中心”

职能化用" +"户在普通用户权限上还拥有SaaS应用 “标准运维” 的职能化权限

" +"审计员在普通用户权限上还拥有SaaS应用 “标准运维”和作业平台的审计权限" msgstr "" -#: .\templates\403.html:6 -msgid "您没有访问权限(403页)" +#: templates/bkaccount/users.html:55 +msgid "选择文件:" msgstr "" -#: .\templates\403.html:20 -msgid "您没有访问权限,请联系系统管理员添加" +#: templates/bkaccount/users.html:57 +msgid "导入用户" msgstr "" -#: .\templates\404.html:6 -msgid "页面找不到(404页)" +#: templates/bkaccount/users.html:58 +msgid "提交" msgstr "" -#: .\templates\404.html:20 -msgid "页面找不到了" +#: templates/bkaccount/users.html:61 +msgid "bk_user_import.xls" msgstr "" -#: .\templates\500.html:6 -msgid "系统异常(500页)" +#: templates/bkaccount/users.html:61 +msgid "点击下载EXCEL模板" msgstr "" -#: .\templates\500.html:20 -msgid "系统出现异常" +#: templates/bkaccount/users.html:65 +msgid "注意:" msgstr "" -#: .\templates\500.html:21 -msgid "努力恢复中,请稍后再试......" +#: templates/bkaccount/users.html:66 +#, python-format +msgid "" +"

1.请下载EXCEL模板文件填写" +"用户数据

2.用户名为必填,包含数字、字母、下划线和点,长度" +"在4-20个字符

3.用户名为唯一标识,重复导入会覆盖已有数据

4.导入用户默认密码为:%(default_paasword)s

5.文件后" +"缀名必须为:.xls.xlsx

6.导入失败请检查" +"EXCEL格式规范,或重新下载模板填写

" msgstr "" -#: .\templates\50x.html:6 .\templates\50x.html.py:19 -msgid "服务故障,努力修复中..." +#: templates/bkaccount/users.html:81 +msgid "新密码:" msgstr "" -#: .\templates\50x.html:20 -msgid "服务出现故障,我们正在紧急修复,给您带来不便,敬请谅解。" +#: templates/bkaccount/users.html:86 templates/bkaccount/users.html.py:92 +msgid "必填" msgstr "" -#: .\templates\account\agreement.part:6 +#: templates/bkaccount/users.html:87 +#, python-format +msgid "" +"请输入密码,长度在8-20个字符,可支持数字、字母以及%(sp_char)s,必须保证密码包" +"含大小写字母和数字 " +msgstr "" + +#: templates/bkaccount/users.html:90 +msgid "确认密码" +msgstr "" + +#: templates/bkaccount/users.html:91 +msgid "再次输入密码" +msgstr "" + +#: templates/csrf_failure.html:6 templates/csrf_failure.html.py:20 +msgid "CSRF验证失败" +msgstr "" + +#: templates/csrf_failure.html:22 +msgid "" +"您看到此消息是由于该站点在提交表单时需要一个CSRF cookie。此项是出于安全考虑," +"以确保您的浏览器没有被第三方劫持。" +msgstr "" + +#: templates/csrf_failure.html:23 +msgid "" +"如果您已经设置浏览器禁用cookies,请重新启用,至少针对这个站点,全部HTTPS请" +"求,或者同源请求(same-origin)启用cookies。" +msgstr "" + +#: templates/csrf_failure.html:24 +msgid "重新登录" +msgstr "" + +#: templates/login/agreement.part:6 msgid "" "
腾讯蓝鲸智云软件许可及服务协议

【首部及导言】

欢迎您使用腾讯蓝鲸" @@ -721,329 +802,43 @@ msgid "" "的版本相冲突的地方,以中文版本为准。(正文完)

腾讯公司

" msgstr "" -#: .\templates\account\agreement.part:124 +#: templates/login/agreement.part:124 msgid "已阅读" msgstr "" -#: .\templates\account\base.html:11 -msgid "用户管理|蓝鲸智云企业版" -msgstr "" - -#: .\templates\account\base.html:12 -msgid "" -"开发者中心,游戏运维,运维,服务器管理,模块配置,监控,腾讯游戏,蓝鲸,智云,devops," -"运维开发,蓝鲸企业版,企业版,作业平台,集成平台,配置平台,管控平台" -msgstr "" - -#: .\templates\account\base.html:13 -msgid "" -"蓝鲸智云软件企业版是由蓝鲸智云团队提供的一套基于PaaS的技术解决方案,旨在改变" -"中国运维行业,帮助企业快速达到基础运维支撑能力,并提升技术人员的DevOps能力。" -"该版本提供了配置平台,作业平台,集成平台等强大功能,用户在使用时,请查阅并遵" -"守《蓝鲸智云软件用户服务协议》。" -msgstr "" - -#: .\templates\account\base.html:42 .\templates\account\base.html.py:97 -#: .\templates\account\login.html:69 -msgid "蓝鲸智云桌面" -msgstr "" - -#: .\templates\account\base.html:43 -msgid "img/logo/logo_user_01.png" +#: templates/login/login.html:10 +msgid "登录|蓝鲸智云" msgstr "" -#: .\templates\account\base.html:45 -msgid "蓝鲸智云用户管理" -msgstr "" - -#: .\templates\account\base.html:46 -msgid "img/logo/logo_user_02.png" -msgstr "" - -#: .\templates\account\base.html:67 .\templates\admin\base_site.html:14 -#: .\templates\admin\login.html:21 -msgid "注销" -msgstr "" - -#: .\templates\account\base.html:82 -msgid "返回顶部" -msgstr "" - -#: .\templates\account\base.html:85 -msgid "返回底部" -msgstr "" - -#: .\templates\account\base.html:94 .\templates\account\login.html:66 -msgid "QQ咨询" -msgstr "" - -#: .\templates\account\base.html:95 .\templates\account\login.html:67 -msgid "蓝鲸论坛" -msgstr "" - -#: .\templates\account\base.html:96 .\templates\account\login.html:68 -msgid "蓝鲸官网" -msgstr "" - -#: .\templates\account\base.html:100 -msgid "蓝鲸智云 版权所有" -msgstr "" - -#: .\templates\account\login.html:10 -msgid "登录|蓝鲸智云企业版" -msgstr "" - -#: .\templates\account\login.html:16 -msgid "img/logo/bk_login.png" -msgstr "" - -#: .\templates\account\login.html:38 +#: templates/login/login.html:22 msgid "账户或者密码错误,请重新输入" msgstr "" -#: .\templates\account\login.html:44 +#: templates/login/login.html:28 msgid "请输入用户名" msgstr "" -#: .\templates\account\login.html:48 +#: templates/login/login.html:32 msgid "请输入用户密码" msgstr "" -#: .\templates\account\login.html:55 +#: templates/login/login.html:39 msgid "登录" msgstr "" -#: .\templates\account\login.html:56 +#: templates/login/login.html:40 msgid "查看用户协议" msgstr "" -#: .\templates\account\login.html:78 -msgid "" -"您的浏览器非Chrome,建议您使用最新版本的Chrome浏览,以保证最好的体验效果" -msgstr "" - -#: .\templates\account\login.html:82 -msgid "企业证书校验无效,请联系系统管理员处理" -msgstr "" - -#: .\templates\account\no_right.html:5 -msgid "你不是管理员, 没有用户管理的权限!" -msgstr "" - -#: .\templates\account\no_right.html:6 -msgid "请找管理员申请权限!" -msgstr "" - -#: .\templates\account\user_role_manage_table.part:50 -msgid "没有用户配置了平台角色" -msgstr "" - -#: .\templates\account\user_table.part:24 -msgid "操作" -msgstr "" - -#: .\templates\account\user_table.part:49 -#: .\templates\account\user_table.part:56 .\templates\account\users.html:30 -msgid "职能化" -msgstr "" - -#: .\templates\account\user_table.part:62 -msgid "取消" -msgstr "" - -#: .\templates\account\user_table.part:63 .\templates\account\users.html:62 -msgid "保存" -msgstr "" - -#: .\templates\account\user_table.part:64 -msgid "编辑" -msgstr "" - -#: .\templates\account\user_table.part:65 -msgid "重置密码" -msgstr "" - -#: .\templates\account\user_table.part:67 -msgid "删除" -msgstr "" - -#: .\templates\account\user_table.part:73 -msgid "没有数据" -msgstr "" - -#: .\templates\account\user_table.part:85 -#: .\templates\account\user_table.part:87 -msgid "上一页" -msgstr "" - -#: .\templates\account\user_table.part:109 -#: .\templates\account\user_table.part:111 -msgid "下一页" -msgstr "" - -#: .\templates\account\users.html:11 -msgid "统一角色管理" -msgstr "" - -#: .\templates\account\users.html:12 -msgid "导出" -msgstr "" - -#: .\templates\account\users.html:13 -msgid "批量导入" -msgstr "" - -#: .\templates\account\users.html:14 -msgid "新增用户" -msgstr "" - -#: .\templates\account\users.html:16 -msgid "用户信息" -msgstr "" - -#: .\templates\account\users.html:24 -msgid "查询:按用户名、中文名" -msgstr "" - -#: .\templates\account\users.html:26 -msgid "所有用户" +#: templates/login/login.html:48 +msgid "青藤云安全提供安全检测" msgstr "" -#: .\templates\account\users.html:33 -msgid "查询" -msgstr "" - -#: .\templates\account\users.html:34 -msgid "新增用户的默认密码为:" -msgstr "" - -#: .\templates\account\users.html:39 -msgid "温馨提示:" -msgstr "" - -#: .\templates\account\users.html:42 -msgid "" -"

管理员可以管理所有用户的信息,具有所有权限

普通" -"用户可以管理自己的用户信息和访问 “桌面”

开发者可以" -"管理自己的用户信息、访问 “桌面” 和访问 “开发者中心”

职能化用户在普通用户权限上还拥有SaaS应用 “标准运维” 的职能化权限

审计" -"员在普通用户权限上还拥有SaaS应用 “标准运维”和作业平台的审计权限

" +#: templates/login/login.html:55 +msgid "关注我们" msgstr "" -#: .\templates\account\users.html:56 -msgid "用户信息管理" -msgstr "" - -#: .\templates\account\users.html:59 -msgid "添加用户:" -msgstr "" - -#: .\templates\account\users.html:61 -msgid "添加" -msgstr "" - -#: .\templates\account\users.html:73 -msgid "选择文件:" -msgstr "" - -#: .\templates\account\users.html:75 -msgid "导入用户" -msgstr "" - -#: .\templates\account\users.html:76 -msgid "提交" -msgstr "" - -#: .\templates\account\users.html:79 -msgid "bk_user_import.xls" -msgstr "" - -#: .\templates\account\users.html:79 -msgid "点击下载EXCEL模板" -msgstr "" - -#: .\templates\account\users.html:83 -msgid "注意:" -msgstr "" - -#: .\templates\account\users.html:84 -#, python-format +#: templates/login/login.html:72 msgid "" -"

1.请下载EXCEL模板文件填写" -"用户数据

2.用户名为必填,包含数字和字母,长度在4-20个字符" -"

3.用户名为唯一标识,重复导入会覆盖已有数据

4.导入" -"用户默认密码为:%(default_paasword)s

5.文件后缀名必须为:" -".xls.xlsx

6.导入失败请检查EXCEL格式规范," -"或重新下载模板填写

" -msgstr "" - -#: .\templates\account\users.html:99 -msgid "新密码:" -msgstr "" - -#: .\templates\account\users.html:104 .\templates\account\users.html.py:110 -msgid "必填" -msgstr "" - -#: .\templates\account\users.html:105 -#, python-format -msgid "" -"请输入密码,长度在8-20个字符,可支持数字、字母以及%(sp_char)s,必须保证密码包" -"含大小写字母和数字 " -msgstr "" - -#: .\templates\account\users.html:108 -msgid "确认密码" -msgstr "" - -#: .\templates\account\users.html:109 -msgid "再次输入密码" -msgstr "" - -#: .\templates\admin\base_site.html:4 -msgid "管理" -msgstr "" - -#: .\templates\admin\base_site.html:7 -msgid "蓝鲸智云后台管理" -msgstr "" - -#: .\templates\admin\base_site.html:12 -msgid "修改密码" -msgstr "" - -#: .\templates\admin\login.html:7 -msgid "您暂时不能访问该站点的后台管理,这是以下原因造成的:" -msgstr "" - -#: .\templates\admin\login.html:15 .\templates\admin\login.html.py:17 -msgid "用户" -msgstr "" - -#: .\templates\admin\login.html:15 -msgid "未激活!" -msgstr "" - -#: .\templates\admin\login.html:17 -msgid "没有管理员权限,请联系管理员!" -msgstr "" - -#: .\templates\csrf_failure.html:6 .\templates\csrf_failure.html.py:20 -msgid "CSRF验证失败" -msgstr "" - -#: .\templates\csrf_failure.html:22 -msgid "" -"您看到此消息是由于该站点在提交表单时需要一个CSRF cookie。此项是出于安全考虑," -"以确保您的浏览器没有被第三方劫持。" -msgstr "" - -#: .\templates\csrf_failure.html:23 -msgid "" -"如果您已经设置浏览器禁用cookies,请重新启用,至少针对这个站点,全部HTTPS请" -"求,或者同源请求(same-origin)启用cookies。" -msgstr "" - -#: .\templates\csrf_failure.html:24 -msgid "重新登录" +"您的浏览器非Chrome,建议您使用最新版本的Chrome浏览,以保证最好的体验效果" msgstr "" diff --git a/paas-ce/paas/login/locale/zh_Hans/LC_MESSAGES/djangojs.po b/paas-ce/paas/login/locale/zh_Hans/LC_MESSAGES/djangojs.po index 3f05dce95..45e16c59d 100644 --- a/paas-ce/paas/login/locale/zh_Hans/LC_MESSAGES/djangojs.po +++ b/paas-ce/paas/login/locale/zh_Hans/LC_MESSAGES/djangojs.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-03-26 23:34+0800\n" +"POT-Creation-Date: 2019-03-28 20:33+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,277 +18,86 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: .\static\admin\js\SelectFilter2.js:45 -#, javascript-format -msgid "Available %s" -msgstr "Available %s" - -#: .\static\admin\js\SelectFilter2.js:46 -#, javascript-format -msgid "" -"This is the list of available %s. You may choose some by selecting them in " -"the box below and then clicking the \"Choose\" arrow between the two boxes." -msgstr "" -"This is the list of available %s. You may choose some by selecting them in " -"the box below and then clicking the \"Choose\" arrow between the two boxes." - -#: .\static\admin\js\SelectFilter2.js:53 -#, javascript-format -msgid "Type into this box to filter down the list of available %s." -msgstr "Type into this box to filter down the list of available %s." - -#: .\static\admin\js\SelectFilter2.js:57 -msgid "Filter" -msgstr "Filter" - -#: .\static\admin\js\SelectFilter2.js:61 -msgid "Choose all" -msgstr "Choose all" - -#: .\static\admin\js\SelectFilter2.js:61 -#, javascript-format -msgid "Click to choose all %s at once." -msgstr "Click to choose all %s at once." - -#: .\static\admin\js\SelectFilter2.js:67 -msgid "Choose" -msgstr "Choose" - -#: .\static\admin\js\SelectFilter2.js:69 -msgid "Remove" -msgstr "Remove" - -#: .\static\admin\js\SelectFilter2.js:75 -#, javascript-format -msgid "Chosen %s" -msgstr "Chosen %s" - -#: .\static\admin\js\SelectFilter2.js:76 -#, javascript-format -msgid "" -"This is the list of chosen %s. You may remove some by selecting them in the " -"box below and then clicking the \"Remove\" arrow between the two boxes." -msgstr "" -"This is the list of chosen %s. You may remove some by selecting them in the " -"box below and then clicking the \"Remove\" arrow between the two boxes." - -#: .\static\admin\js\SelectFilter2.js:80 -msgid "Remove all" -msgstr "Remove all" - -#: .\static\admin\js\SelectFilter2.js:80 -#, javascript-format -msgid "Click to remove all chosen %s at once." -msgstr "Click to remove all chosen %s at once." - -#: .\static\admin\js\actions.js:22 .\static\admin\js\actions.min.js:1 -msgid "%(sel)s of %(cnt)s selected" -msgid_plural "%(sel)s of %(cnt)s selected" -msgstr[0] "%(sel)s of %(cnt)s selected" - -#: .\static\admin\js\actions.js:114 .\static\admin\js\actions.min.js:4 -msgid "" -"You have unsaved changes on individual editable fields. If you run an " -"action, your unsaved changes will be lost." -msgstr "" -"You have unsaved changes on individual editable fields. If you run an " -"action, your unsaved changes will be lost." - -#: .\static\admin\js\actions.js:126 .\static\admin\js\actions.min.js:5 -msgid "" -"You have selected an action, but you haven't saved your changes to " -"individual fields yet. Please click OK to save. You'll need to re-run the " -"action." -msgstr "" -"You have selected an action, but you haven't saved your changes to " -"individual fields yet. Please click OK to save. You'll need to re-run the " -"action." - -#: .\static\admin\js\actions.js:128 .\static\admin\js\actions.min.js:5 -msgid "" -"You have selected an action, and you haven't made any changes on individual " -"fields. You're probably looking for the Go button rather than the Save " -"button." -msgstr "" -"You have selected an action, and you haven't made any changes on individual " -"fields. You're probably looking for the Go button rather than the Save " -"button." - -#: .\static\admin\js\admin\DateTimeShortcuts.js:79 -#, javascript-format -msgid "Note: You are %s hour ahead of server time." -msgid_plural "Note: You are %s hours ahead of server time." -msgstr[0] "Note: You are %s hours ahead of server time." - -#: .\static\admin\js\admin\DateTimeShortcuts.js:87 -#, javascript-format -msgid "Note: You are %s hour behind server time." -msgid_plural "Note: You are %s hours behind server time." -msgstr[0] "Note: You are %s hour behind server time." - -#: .\static\admin\js\admin\DateTimeShortcuts.js:114 -#: .\static\admin\js\admin\DateTimeShortcuts.js:149 -msgid "Now" -msgstr "Now" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:118 -msgid "Clock" -msgstr "Clock" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:146 -msgid "Choose a time" -msgstr "Choose a time" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:150 -msgid "Midnight" -msgstr "Midnight" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:151 -msgid "6 a.m." -msgstr "6 a.m." - -#: .\static\admin\js\admin\DateTimeShortcuts.js:152 -msgid "Noon" -msgstr "Noon" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:156 -#: .\static\admin\js\admin\DateTimeShortcuts.js:276 -msgid "Cancel" -msgstr "Cancel" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:216 -#: .\static\admin\js\admin\DateTimeShortcuts.js:269 -msgid "Today" -msgstr "Today" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:220 -msgid "Calendar" -msgstr "Calendar" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:267 -msgid "Yesterday" -msgstr "Yesterday" - -#: .\static\admin\js\admin\DateTimeShortcuts.js:271 -msgid "Tomorrow" -msgstr "Tomorrow" - -#: .\static\admin\js\calendar.js:8 -msgid "" -"January February March April May June July August September October November " -"December" -msgstr "" -"January February March April May June July August September October November " -"December" - -#: .\static\admin\js\calendar.js:9 -msgid "S M T W T F S" -msgstr "S M T W T F S" - -#: .\static\admin\js\collapse.js:8 .\static\admin\js\collapse.js:19 -#: .\static\admin\js\collapse.min.js:1 -msgid "Show" -msgstr "Show" - -#: .\static\admin\js\collapse.js:16 .\static\admin\js\collapse.min.js:1 -msgid "Hide" -msgstr "Hide" - -#: .\static\js\csrftoken.js:20 .\static\js\csrftoken.js:31 -#: .\static\js\csrftoken.min.js:1 +#: static/js/csrftoken.js:27 static/js/csrftoken.js:38 +#: static/js/csrftoken.min.js:8 msgid "提示" msgstr "提示" -#: .\static\js\csrftoken.js:33 .\static\js\csrftoken.min.js:1 +#: static/js/csrftoken.js:40 static/js/csrftoken.min.js:8 msgid "系统出现异常:" msgstr "系统出现异常:" -#: .\static\js\role_manage.js:3 .\static\js\role_manage.js:11 -#: .\static\js\role_manage.min.js:1 -msgid "输入用户名" -msgstr "输入用户名" - -#: .\static\js\role_manage.js:26 .\static\js\role_manage.min.js:1 -#, fuzzy -#| msgid "用户" -msgid "用户(" -msgstr "用户(" - -#: .\static\js\role_manage.js:26 .\static\js\role_manage.min.js:1 -msgid ")已存在" -msgstr ")已存在" - -#: .\static\js\users.js:13 .\static\js\users.min.js:1 +#: static/js/users.js:20 static/js/users.min.js:8 msgid "不可同时修改多个用户信息,请先保存编辑中的用户信息" msgstr "不可同时修改多个用户信息,请先保存编辑中的用户信息" -#: .\static\js\users.js:44 .\static\js\users.js:220 .\static\js\users.min.js:1 +#: static/js/users.js:51 static/js/users.js:206 static/js/users.min.js:8 msgid "请输入用户名" msgstr "请输入用户名" -#: .\static\js\users.js:47 .\static\js\users.min.js:1 +#: static/js/users.js:54 static/js/users.min.js:8 msgid "请输入姓名" msgstr "请输入姓名" -#: .\static\js\users.js:50 .\static\js\users.min.js:1 +#: static/js/users.js:57 static/js/users.min.js:8 msgid "请输入联系电话" msgstr "请输入联系电话" -#: .\static\js\users.js:53 .\static\js\users.js:223 .\static\js\users.min.js:1 +#: static/js/users.js:60 static/js/users.js:209 static/js/users.min.js:8 msgid "请输入邮箱" msgstr "请输入邮箱" -#: .\static\js\users.js:57 .\static\js\users.min.js:1 +#: static/js/users.js:64 static/js/users.min.js:8 msgid "普通用户" msgstr "普通用户" -#: .\static\js\users.js:58 .\static\js\users.min.js:1 +#: static/js/users.js:65 static/js/users.min.js:8 msgid "管理员" msgstr "管理员" -#: .\static\js\users.js:59 .\static\js\users.min.js:1 +#: static/js/users.js:66 static/js/users.min.js:8 msgid "开发者" msgstr "开发者" -#: .\static\js\users.js:60 .\static\js\users.min.js:1 -msgid "职能化" -msgstr "职能化" +#: static/js/users.js:67 static/js/users.min.js:8 +msgid "职能化用户" +msgstr "职能化用户" -#: .\static\js\users.js:61 .\static\js\users.min.js:1 +#: static/js/users.js:68 static/js/users.min.js:8 msgid "审计员" msgstr "审计员" -#: .\static\js\users.js:65 .\static\js\users.js:309 .\static\js\users.js:328 -#: .\static\js\users.min.js:1 +#: static/js/users.js:72 static/js/users.js:296 static/js/users.js:315 +#: static/js/users.min.js:8 msgid "取消" msgstr "取消" -#: .\static\js\users.js:66 .\static\js\users.min.js:1 +#: static/js/users.js:73 static/js/users.min.js:8 msgid "保存" msgstr "保存" -#: .\static\js\users.js:67 .\static\js\users.min.js:1 +#: static/js/users.js:74 static/js/users.min.js:8 msgid "编辑" msgstr "编辑" -#: .\static\js\users.js:68 .\static\js\users.min.js:1 +#: static/js/users.js:75 static/js/users.min.js:8 msgid "删除" msgstr "删除" -#: .\static\js\users.js:69 .\static\js\users.js:324 .\static\js\users.js:331 -#: .\static\js\users.min.js:1 +#: static/js/users.js:76 static/js/users.js:311 static/js/users.js:318 +#: static/js/users.min.js:8 msgid "重置密码" msgstr "重置密码" -#: .\static\js\users.js:88 .\static\js\users.min.js:1 +#: static/js/users.js:95 static/js/users.min.js:8 msgid "批量导入用户" msgstr "批量导入用户" -#: .\static\js\users.js:101 .\static\js\users.min.js:1 +#: static/js/users.js:108 static/js/users.min.js:8 msgid "请选择一个文件" msgstr "请选择一个文件" -#: .\static\js\users.js:116 .\static\js\users.min.js:1 +#: static/js/users.js:123 static/js/users.min.js:8 #, fuzzy #| msgid "" #| "用户名只能包含数字、字母和点,且长度在4-20个字符, 且必须以字母或数字开头" @@ -298,70 +107,213 @@ msgid "" msgstr "" "用户名只能包含数字、字母和点,且长度在4-20个字符, 且必须以字母或数字开头" -#: .\static\js\users.js:121 .\static\js\users.min.js:1 +#: static/js/users.js:128 static/js/users.min.js:8 msgid "中文名只能包含数字、字母、中文汉字、下划线,长度在1-16个字符" msgstr "中文名只能包含数字、字母、中文汉字、下划线,长度在1-16个字符" -#: .\static\js\users.js:126 .\static\js\users.min.js:1 +#: static/js/users.js:133 static/js/users.min.js:8 msgid "仅支持中国大陆手机号码(11位数字)" msgstr "仅支持中国大陆手机号码(11位数字)" -#: .\static\js\users.js:131 .\static\js\users.min.js:1 +#: static/js/users.js:138 static/js/users.min.js:8 msgid "请输入正确的邮箱格式" msgstr "请输入正确的邮箱格式" -#: .\static\js\users.js:136 .\static\js\users.min.js:1 +#: static/js/users.js:143 static/js/users.min.js:8 msgid "请选择角色" msgstr "请选择角色" -#: .\static\js\users.js:155 .\static\js\users.min.js:1 +#: static/js/users.js:157 static/js/users.min.js:8 msgid "保存成功" msgstr "保存成功" -#: .\static\js\users.js:165 .\static\js\users.min.js:1 -msgid "保存失败" -msgstr "保存失败" - -#: .\static\js\users.js:183 .\static\js\users.min.js:1 +#: static/js/users.js:174 static/js/users.min.js:8 msgid "添加成功" msgstr "添加成功" -#: .\static\js\users.js:196 .\static\js\users.min.js:1 -msgid "添加失败" -msgstr "添加失败" - -#: .\static\js\users.js:221 .\static\js\users.min.js:1 +#: static/js/users.js:207 static/js/users.min.js:8 msgid "请输入中文名" msgstr "请输入中文名" -#: .\static\js\users.js:222 .\static\js\users.min.js:1 +#: static/js/users.js:208 static/js/users.min.js:8 msgid "请输入手机号" msgstr "请输入手机号" -#: .\static\js\users.js:282 .\static\js\users.min.js:1 +#: static/js/users.js:268 static/js/users.min.js:8 msgid "您确定删除该用户吗?" msgstr "您确定删除该用户吗?" -#: .\static\js\users.js:282 .\static\js\users.min.js:1 +#: static/js/users.js:268 static/js/users.min.js:8 msgid "用户名 : " msgstr "用户名 : " -#: .\static\js\users.js:285 .\static\js\users.min.js:1 +#: static/js/users.js:271 static/js/users.min.js:8 msgid "删除确认" msgstr "删除确认" -#: .\static\js\users.js:291 .\static\js\users.min.js:1 +#: static/js/users.js:277 static/js/users.min.js:8 msgid "正在进行删除操作,请稍后..." msgstr "正在进行删除操作,请稍后..." -#: .\static\js\users.js:308 .\static\js\users.min.js:1 +#: static/js/users.js:295 static/js/users.min.js:8 msgid "确认删除" msgstr "确认删除" -#: .\static\js\users.js:358 .\static\js\users.min.js:1 +#: static/js/users.js:345 static/js/users.min.js:8 msgid "两次输入的新密码不一致" msgstr "两次输入的新密码不一致" -#: .\static\js\users.js:389 .\static\js\users.min.js:1 +#: static/js/users.js:370 static/js/users.min.js:8 msgid "密码重置成功" msgstr "密码重置成功" + +#~ msgid "Available %s" +#~ msgstr "Available %s" + +#~ msgid "" +#~ "This is the list of available %s. You may choose some by selecting them " +#~ "in the box below and then clicking the \"Choose\" arrow between the two " +#~ "boxes." +#~ msgstr "" +#~ "This is the list of available %s. You may choose some by selecting them " +#~ "in the box below and then clicking the \"Choose\" arrow between the two " +#~ "boxes." + +#~ msgid "Type into this box to filter down the list of available %s." +#~ msgstr "Type into this box to filter down the list of available %s." + +#~ msgid "Filter" +#~ msgstr "Filter" + +#~ msgid "Choose all" +#~ msgstr "Choose all" + +#~ msgid "Click to choose all %s at once." +#~ msgstr "Click to choose all %s at once." + +#~ msgid "Choose" +#~ msgstr "Choose" + +#~ msgid "Remove" +#~ msgstr "Remove" + +#~ msgid "Chosen %s" +#~ msgstr "Chosen %s" + +#~ msgid "" +#~ "This is the list of chosen %s. You may remove some by selecting them in " +#~ "the box below and then clicking the \"Remove\" arrow between the two " +#~ "boxes." +#~ msgstr "" +#~ "This is the list of chosen %s. You may remove some by selecting them in " +#~ "the box below and then clicking the \"Remove\" arrow between the two " +#~ "boxes." + +#~ msgid "Remove all" +#~ msgstr "Remove all" + +#~ msgid "Click to remove all chosen %s at once." +#~ msgstr "Click to remove all chosen %s at once." + +#~ msgid "%(sel)s of %(cnt)s selected" +#~ msgid_plural "%(sel)s of %(cnt)s selected" +#~ msgstr[0] "%(sel)s of %(cnt)s selected" + +#~ msgid "" +#~ "You have unsaved changes on individual editable fields. If you run an " +#~ "action, your unsaved changes will be lost." +#~ msgstr "" +#~ "You have unsaved changes on individual editable fields. If you run an " +#~ "action, your unsaved changes will be lost." + +#~ msgid "" +#~ "You have selected an action, but you haven't saved your changes to " +#~ "individual fields yet. Please click OK to save. You'll need to re-run the " +#~ "action." +#~ msgstr "" +#~ "You have selected an action, but you haven't saved your changes to " +#~ "individual fields yet. Please click OK to save. You'll need to re-run the " +#~ "action." + +#~ msgid "" +#~ "You have selected an action, and you haven't made any changes on " +#~ "individual fields. You're probably looking for the Go button rather than " +#~ "the Save button." +#~ msgstr "" +#~ "You have selected an action, and you haven't made any changes on " +#~ "individual fields. You're probably looking for the Go button rather than " +#~ "the Save button." + +#~ msgid "Note: You are %s hour ahead of server time." +#~ msgid_plural "Note: You are %s hours ahead of server time." +#~ msgstr[0] "Note: You are %s hours ahead of server time." + +#~ msgid "Note: You are %s hour behind server time." +#~ msgid_plural "Note: You are %s hours behind server time." +#~ msgstr[0] "Note: You are %s hour behind server time." + +#~ msgid "Now" +#~ msgstr "Now" + +#~ msgid "Clock" +#~ msgstr "Clock" + +#~ msgid "Choose a time" +#~ msgstr "Choose a time" + +#~ msgid "Midnight" +#~ msgstr "Midnight" + +#~ msgid "6 a.m." +#~ msgstr "6 a.m." + +#~ msgid "Noon" +#~ msgstr "Noon" + +#~ msgid "Cancel" +#~ msgstr "Cancel" + +#~ msgid "Today" +#~ msgstr "Today" + +#~ msgid "Calendar" +#~ msgstr "Calendar" + +#~ msgid "Yesterday" +#~ msgstr "Yesterday" + +#~ msgid "Tomorrow" +#~ msgstr "Tomorrow" + +#~ msgid "" +#~ "January February March April May June July August September October " +#~ "November December" +#~ msgstr "" +#~ "January February March April May June July August September October " +#~ "November December" + +#~ msgid "S M T W T F S" +#~ msgstr "S M T W T F S" + +#~ msgid "Show" +#~ msgstr "Show" + +#~ msgid "Hide" +#~ msgstr "Hide" + +#~ msgid "输入用户名" +#~ msgstr "输入用户名" + +#, fuzzy +#~| msgid "用户" +#~ msgid "用户(" +#~ msgstr "用户(" + +#~ msgid ")已存在" +#~ msgstr ")已存在" + +#~ msgid "保存失败" +#~ msgstr "保存失败" + +#~ msgid "添加失败" +#~ msgstr "添加失败" diff --git a/paas-ce/paas/login/on_migrate b/paas-ce/paas/login/on_migrate deleted file mode 100755 index 6eb90a23a..000000000 --- a/paas-ce/paas/login/on_migrate +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -source /root/.bkrc -source $CTRL_DIR/functions -export BK_ENV=production - -workon login || fail "Abort" -python manage.py migrate || fail "Abort" diff --git a/paas-ce/paas/login/requirements.txt b/paas-ce/paas/login/requirements.txt index 6e426494e..fdaa33316 100644 --- a/paas-ce/paas/login/requirements.txt +++ b/paas-ce/paas/login/requirements.txt @@ -3,7 +3,7 @@ dj-static==0.0.6 pycrypto==2.6.1 requests==2.21.0 pymysql==0.6.7 -gunicorn==19.6.0 +gunicorn==19.9.0 uWSGI==2.0.13.1 xlrd==1.0.0 xlwt==1.1.2 diff --git a/paas-ce/paas/login/static/bk_user_import.xls b/paas-ce/paas/login/static/bk_user_import.xls index f6b6e67473daf3764c9222078cd88309a632019a..960916b39a4e8ca8ad7f379016225d12bbb7cec5 100644 GIT binary patch delta 5766 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 X>E^?QQ2ao1b1sxHOGevOTk(GYqL=8t diff --git a/paas-ce/paas/login/static/bk_user_import_en.xls b/paas-ce/paas/login/static/bk_user_import_en.xls index d8d8466dc45c6fc87fddb28b902a08ee82fd1b2c..8cf7a50ade8879d38c9694b35eea01bfed31d5f2 100644 GIT binary patch delta 4392 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 E0?qoeTmS$7 literal 0 HcmV?d00001 diff --git a/paas-ce/paas/login/static/img/getheadimg.jpg b/paas-ce/paas/login/static/img/getheadimg.jpg old mode 100755 new mode 100644 index 715f359824326cf60979f1d449f17e68639ab9ef..8ca00ac6ce560e98ba4e416de9e24b93c953f8d3 GIT binary patch literal 10913 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 literal 2300 zcmaJ@YdBPE8=g)!a!AAu)iSt9=41>rW5k#-&0u7YDGD{Gg&Ahnm>CS&rAY^y`Z|3j zicM5HDA_sX)TphKHd2a^T|UP|2NY_LcG};MuWwz~TF?8w*L~m5^SsafW2FZ8uhZ8x z*M-4g`V2airHR1otF5K^$`cdcX~J@acd#N53RlE)Wgv_!fOsIl5OX6y7RVJO#M}W% zFxUbsAv;(R%=9DjAu*CWi$N;IQVkmhBY7yLTz(X&0C-@8P~r}MeZ3YA2nFu&ARH6T zlv2P*Aw5wB1}6Hm`H4|{f&lKZ79c5!8UZn=-~viB?2AQ=eYkT?V%jd2EC2}leMyEx7OMedP+i zUyI9kxhPFBsM)#x*PQ2$H0GIIesis6^Ue35L}PZD#?_rQ6USk&MKKI2nXPQU7!>7q zB*J97Pwke9+sUP9T~#a7bF~p!;*cI48d|#VX)Boa)Y-Qb^c`&|jrKMD-1wn>xXn{)BIbsw@bY=)YMe^7zCNHEk@V)lnxFVSCklSgT9vdXiTTqg zAw4}sq_)qQ=cJBRxg@n+6q=j)e@f13L-GZ`+I3wd$Ns$7z;aqwN5_}c;(N{puhz#? zC()s)9lg|!E>pks?gpR!ne~RJYZ4;xQ@-kT!&X)|?SbFMR&${0mip!U^$kahJG|Pe zIdu&SjdJqu4b<((B{8j5g_sbrk)BT6^)`zNOdhcc6*|!8sO!z`Eh&x#GEC;8`7e9V zjYZ$cT(pJ3wGx%#sI2O&Q;j^1nY-nFo8D8nUtg>Lg^w8_g-XmsYaFf=X_Y4&UpF$Lz5eRVOrxa!+y(3H*8c7jXiH(u)^fsHtN~>(dupe*CBPC^_t;0JJH>H zyg~#=EB_|H?#|mwO^OSY&9){`!2{+RE(TD=$qBuz$cG*p)ST3DG!q5(*bS@ixq| zW+?p*$$b+J%+& zhd+9h2gsjTb}WEbJ)4|fx}}me?}VR0VW_DCEji%esLk%H#~E9HL0UiW{b=d0)T8Z- zj+;z>INI!rvZdnsmztTc4VKxxVQBYGGycp(bEc>Gqnj@-X@ccN3q2FVaDRMirSHY2 z{qdmeMVz{3-{BqIDN|#+dN;HT?GA*J@rY&W{N8anLr8ZhN_%+=+7xoaHF??4PWp;N zgBZ)o+UMEkl)ApupG#iG#cVbZBy4_TaM|Zfeg=A}9MCCA(Hm{a+Qz9Fzjt-RKqiac z8fC>X4tU2Qk#=mHq(8=WTLeFdH`McT&D|?}Y-#D$C-3t2E_4i2ndzE#6h9cQ8#^SF zvIw9G#<~+)!iyyz%GQbvH@(&u8~pE+_pcT?m@Js43^WIxT^3YXnfDPMQc!1svoPJ> zU4FKqcO>`Rw#dycBhiwg?M0O$uD$+*aY*E0`prEVjj1CWFDHi2J9hK8;1Io+)n^`> zp$;H*%vRp$a5J}v>TZ88fhS^VGMhyx5;DM$WeYJ60VjdqmZcT6uJH7k-5rc@+ z@|eamSI74cwRI3a?I2Y(9_b}C=%i6zl$BJ}NS^j2k$-&ux}vd1S^RmV^J7;}539`M z;MSS~mq%{LS70eKGyGkh?wy-_yd%PCv>z%u&llvfO'+ gettext("普通用户") +'', ' ', ' ', - ' ', + ' ', ' ', ' ', ' ', @@ -95,19 +108,19 @@ $('.user_import_btn').on('click', function(){ title:gettext("批量导入用户"), lock: true, width: 560, - content: $("#user_import_div").get(0) + content: $("#user_import_div").get(0), + }) + // 导入用户 + $('#user_import_div').on('click', '.import_btn', function(){ + var user_file = $("#data_files").val(); + if(user_file){ + $("#sumbit_import").click(); + }else{ + $("#error_msg").text(gettext('请选择一个文件')); + } }) $("#error_msg").text(''); }) -// 导入用户 -$('#user_import_div').on('click', '.import_btn', function(){ - var user_file = $("#data_files").val(); - if(user_file){ - $("#sumbit_import").click(); - }else{ - $("#error_msg").text(gettext('请选择一个文件')); - } -}) // 保存 $('#user_table_div').on('click','.user_save_btn',function(){ var btn_obj = $(this); @@ -160,6 +173,7 @@ $('#user_table_div').on('click','.user_save_btn',function(){ curRecord.removeClass('user_edit_status'); var cur_page = $("#current_page").val(); get_user(cur_page); + // get_all_users(1); }else{ art.dialog({id: 'bktips', width: 300, icon: 'error', lock: true, content: data.message}); } @@ -178,7 +192,8 @@ $('#user_table_div').on('click','.user_save_btn',function(){ curRecord.find('input').attr('disabled','disabled'); curRecord.find('select').attr('disabled','disabled'); curRecord.removeClass('user_edit_status'); - get_user(1); + // get_user(1); + get_all_users(1); }else{ art.dialog({id: 'bktips', width: 300,icon: 'error',lock: true,content: data.message}); //curRecord.remove(); @@ -283,7 +298,8 @@ $('#user_table_div').on('click','.user_del_btn',function(){ if(data.result){ art.dialog({id: 'bktips', width: 300,icon: 'succeed',lock: true,content: data.message}).time(2); curRecord.remove(); - get_user(1); + // get_user(1); + get_all_users(1); }else{ art.dialog({id: 'bktips', width: 300,icon: 'error',lock: true,content: data.message}); } diff --git a/paas-ce/paas/login/static/js/users.min.js b/paas-ce/paas/login/static/js/users.min.js index 45ee2def0..1cc4a330e 100644 --- a/paas-ce/paas/login/static/js/users.min.js +++ b/paas-ce/paas/login/static/js/users.min.js @@ -5,4 +5,4 @@ * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -function enter_keyword(t){"13"==t.keyCode&&$("#serach_user").click()}function is_user_edit_status(){return $("#user_table_div table tbody tr.user_edit_status").length>0&&(art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:gettext("不可同时修改多个用户信息,请先保存编辑中的用户信息")}).time(5),!0)}function get_user(t){var e=$("#search_data").val(),r=$("#search_role").val(),a=site_url+"accounts/user/list/query/";$.get(a,{page:t,search_data:e,search_role:r},function(t){$("#user_table_div").html(t)})}$("#search_role").on("onchange",function(){get_user(1)}),$("#serach_user").on("click",function(){get_user(1)}),$(".user_add_btn").on("click",function(){if(is_user_edit_status())return!1;var t=[''," ",' '," "," ",' '," "," ",' '," "," ",' '," "," ",' "," "," ",' ",' ",' ',' ',' '," ",""].join("");return $("#no_record_row").hide(),$("#user_table").prepend($(t)),!1}),$(".user_export_btn").on("click",function(){window.location.href=site_url+"accounts/user/export/"}),$(".user_import_btn").on("click",function(){$("#data_files").val(""),art.dialog({id:"bktips",title:gettext("批量导入用户"),lock:!0,width:560,content:$("#user_import_div").get(0)}),$("#error_msg").text("")}),$("#user_import_div").on("click",".import_btn",function(){$("#data_files").val()?$("#sumbit_import").click():$("#error_msg").text(gettext("请选择一个文件"))}),$("#user_table_div").on("click",".user_save_btn",function(){var t=($(this),$(this).closest(".user_record")),e=t.attr("user_id"),r=$.trim(t.find(".u_username").val()),a=$.trim(t.find(".u_chname").val()),i=$.trim(t.find(".u_phone").val()),s=$.trim(t.find(".u_email").val()),n=$.trim(t.find(".u_role").val());if(!r.match(/^[A-Za-z0-9][A-Za-z0-9._]{2,18}[A-Za-z0-9]$/))return art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:gettext("用户名只能包含数字、字母、下划线和点,且长度在4-20个字符, 且必须以字母或数字开头")}),t.find(".u_username").focus(),!1;if(!a.match(/^[\u4e00-\u9fa5a-zA-Z0-9_]{1,16}$/))return art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:gettext("中文名只能包含数字、字母、中文汉字、下划线,长度在1-16个字符")}),t.find(".u_chname").focus(),!1;if(!i.match(/^\d{10,11}$/))return art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:gettext("仅支持中国大陆手机号码(11位数字)")}),t.find(".u_phone").focus(),!1;if(!s.match(/^[A-Za-z0-9]+([-_.][A-Za-z0-9]+)*@([A-Za-z0-9]+[-.])+[A-Za-z0-9]{2,5}$/))return art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:gettext("请输入正确的邮箱格式")}),t.find(".u_email").focus(),!1;if(!n)return art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:gettext("请选择角色")}),t.find(".u_role").focus(),!1;if(e){var o=site_url+"accounts/user/"+e+"/";$.ajax({url:o,type:"PUT",data:{username:r,chname:a,phone:i,role:n,email:s},success:function(e){if(e.result){art.dialog({id:"bktips",width:300,icon:"succeed",lock:!0,content:gettext("保存成功")}).time(1),t.find("input").attr("disabled","disabled"),t.find("select").attr("disabled","disabled"),t.removeClass("user_edit_status");get_user($("#current_page").val())}else art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:e.message})},dataType:"json"})}else{var o=site_url+"accounts/user/";$.post(o,{username:r,chname:a,phone:i,role:n,email:s},function(e){e.result?(art.dialog({id:"bktips",width:300,icon:"succeed",lock:!0,content:gettext("添加成功")}).time(1),user_data=e.data,t.attr("user_id",user_data.user_id),t.find("input").attr("disabled","disabled"),t.find("select").attr("disabled","disabled"),t.removeClass("user_edit_status"),get_user(1)):art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:e.message})},"json")}return!1}),$("#user_table_div").on("click",".user_edit_btn",function(){if(is_user_edit_status())return!1;var t=$(this).closest(".user_record");t.addClass("user_edit_status"),t.find("input").removeAttr("disabled"),t.find(".u_username").attr("disabled","disabled"),t.find("select").removeAttr("disabled");var e=$.trim(t.find(".u_username").val()),r=$.trim(t.find(".u_chname").val()),a=$.trim(t.find(".u_phone").val()),i=$.trim(t.find(".u_role").val()),s=$.trim(t.find(".u_email").val());return t.find(".u_username").attr("placeholder",gettext("请输入用户名")),t.find(".u_chname").attr("placeholder",gettext("请输入中文名")),t.find(".u_phone").attr("placeholder",gettext("请输入手机号")),t.find(".u_email").attr("placeholder",gettext("请输入邮箱")),t.attr("data-old-username",e),t.attr("data-old-chname",r),t.attr("data-old-phone",a),t.attr("data-old-role",i),t.attr("data-old-email",s),!1}),$("#user_table_div").on("click",".user_cancel_btn",function(){var t=$(this).closest(".user_record");t.removeClass("user_edit_status"),t.find("input").attr("disabled","disabled"),t.find("select").attr("disabled","disabled"),t.find(".u_username").attr("placeholder","--"),t.find(".u_chname").attr("placeholder","--"),t.find(".u_phone").attr("placeholder","--"),t.find(".u_email").attr("placeholder","--");var e=t.attr("data-old-username"),r=t.attr("data-old-chname"),a=t.attr("data-old-phone"),i=t.attr("data-old-role"),s=t.attr("data-old-email");return e||r||a||s?(t.find(".u_username").val(e),t.find(".u_chname").val(r),t.find(".u_phone").val(a),t.find(".u_role").val(i),t.find(".u_email").val(s)):t.remove(),0==$("#user_table").find(".user_record").length&&$("#no_record_row").show(),!1}),$("#user_table_div").on("click",".user_del_btn",function(){var t=$(this).closest(".user_record"),e=t.attr("user_id"),r=t.find(".u_username").val();t.find(".u_chname").val();if(e){var a=site_url+"accounts/user/"+e+"/",i="
"+gettext("您确定删除该用户吗?")+"
"+gettext("用户名 : ")+r+"
";art.dialog({title:gettext("删除确认"),width:340,icon:"question",lock:!0,content:i,ok:function(){art.dialog({id:"bktips",width:300,icon:"warning",lock:!0,content:gettext("正在进行删除操作,请稍后...")}),$.ajax({url:a,type:"DELETE",success:function(e){art.dialog({id:"bktips"}).close(),e.result?(art.dialog({id:"bktips",width:300,icon:"succeed",lock:!0,content:e.message}).time(2),t.remove(),get_user(1)):art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:e.message})},dataType:"json"})},cancel:function(){},okVal:gettext("确认删除"),cancelVal:gettext("取消")})}}),$("#user_table_div").on("click",".user_rest_btn",function(){$(".error_tip").hide(),$(".password_input").val(""),$("#password_tip").text("");var t=$(this).closest(".user_record"),e=t.attr("user_id");t.find(".u_username").val();art.dialog({id:"bkpwd",title:gettext("重置密码"),lock:!0,width:505,content:$("#change_password_div").get(0),cancelVal:gettext("取消"),cancel:function(){},okVal:gettext("重置密码"),ok:function(){var t=!0;if($(".error_tip").hide(),$("#pattern_tip").css("color","black"),$(".password_input").each(function(){var e=$.trim($(this).val());return e?e.match(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[A-Za-z0-9!@#\$%\^\*\(\)-_\+=]{8,20}$/)||"password1"!=$(this).attr("name")?void 0:($("#pattern_tip").css("color","red"),$(this).focus(),t=!1,!1):($(this).next(".error_tip").show(),$(this).focus(),t=!1,!1)}),!t)return!1;var r=$.trim($("#id_password1").val()),a=$.trim($("#id_password2").val());if(r!=a&&($("#password_tip").text(gettext("两次输入的新密码不一致")),t=!1),!t)return!1;var i=site_url+"accounts/user/"+e+"/password/",s=!0;if($.ajax({url:i,type:"PUT",data:{new_password1:r,new_password2:a},success:function(t){t.result||($("#password_tip").text(t.message),s=!1)},dataType:"json",async:!1}),!s)return!1;art.dialog({width:300,icon:"succeed",lock:!0,content:gettext("密码重置成功")}).time(2)}})}); \ No newline at end of file +function enter_keyword(t){"13"==t.keyCode&&$("#serach_user").click()}function is_user_edit_status(){return $("#user_table_div table tbody tr.user_edit_status").length>0&&(art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:gettext("不可同时修改多个用户信息,请先保存编辑中的用户信息")}).time(5),!0)}function get_user(t){var e=$("#search_data").val(),r=$("#search_role").val(),a=site_url+"accounts/user/list/query/";$.get(a,{page:t,search_data:e,search_role:r},function(t){$("#user_table_div").html(t)})}function get_all_users(t){var e=site_url+"accounts/user/list/query/";$.get(e,{page:t,search_data:"",search_role:""},function(t){$("#user_table_div").html(t)})}$("#search_role").on("onchange",function(){get_user(1)}),$("#serach_user").on("click",function(){get_user(1)}),$(".user_add_btn").on("click",function(){if(is_user_edit_status())return!1;var t=[''," ",' '," "," ",' '," "," ",' '," "," ",' '," "," ",' "," "," ",' ",' ",' ',' ',' '," ",""].join("");return $("#no_record_row").hide(),$("#user_table").prepend($(t)),!1}),$(".user_export_btn").on("click",function(){window.location.href=site_url+"accounts/user/export/"}),$(".user_import_btn").on("click",function(){$("#data_files").val(""),art.dialog({id:"bktips",title:gettext("批量导入用户"),lock:!0,width:560,content:$("#user_import_div").get(0)}),$("#user_import_div").on("click",".import_btn",function(){$("#data_files").val()?$("#sumbit_import").click():$("#error_msg").text(gettext("请选择一个文件"))}),$("#error_msg").text("")}),$("#user_table_div").on("click",".user_save_btn",function(){var t=($(this),$(this).closest(".user_record")),e=t.attr("user_id"),r=$.trim(t.find(".u_username").val()),a=$.trim(t.find(".u_chname").val()),i=$.trim(t.find(".u_phone").val()),s=$.trim(t.find(".u_email").val()),n=$.trim(t.find(".u_role").val());if(!r.match(/^[A-Za-z0-9][A-Za-z0-9._]{2,18}[A-Za-z0-9]$/))return art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:gettext("用户名只能包含数字、字母、下划线和点,且长度在4-20个字符, 且必须以字母或数字开头")}),t.find(".u_username").focus(),!1;if(!a.match(/^[\u4e00-\u9fa5a-zA-Z0-9_]{1,16}$/))return art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:gettext("中文名只能包含数字、字母、中文汉字、下划线,长度在1-16个字符")}),t.find(".u_chname").focus(),!1;if(!i.match(/^\d{10,11}$/))return art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:gettext("仅支持中国大陆手机号码(11位数字)")}),t.find(".u_phone").focus(),!1;if(!s.match(/^[A-Za-z0-9]+([-_.][A-Za-z0-9]+)*@([A-Za-z0-9]+[-.])+[A-Za-z0-9]{2,5}$/))return art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:gettext("请输入正确的邮箱格式")}),t.find(".u_email").focus(),!1;if(!n)return art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:gettext("请选择角色")}),t.find(".u_role").focus(),!1;if(e){var o=site_url+"accounts/user/"+e+"/";$.ajax({url:o,type:"PUT",data:{username:r,chname:a,phone:i,role:n,email:s},success:function(e){if(e.result){art.dialog({id:"bktips",width:300,icon:"succeed",lock:!0,content:gettext("保存成功")}).time(1),t.find("input").attr("disabled","disabled"),t.find("select").attr("disabled","disabled"),t.removeClass("user_edit_status");get_user($("#current_page").val())}else art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:e.message})},dataType:"json"})}else{var o=site_url+"accounts/user/";$.post(o,{username:r,chname:a,phone:i,role:n,email:s},function(e){e.result?(art.dialog({id:"bktips",width:300,icon:"succeed",lock:!0,content:gettext("添加成功")}).time(1),user_data=e.data,t.attr("user_id",user_data.user_id),t.find("input").attr("disabled","disabled"),t.find("select").attr("disabled","disabled"),t.removeClass("user_edit_status"),get_all_users(1)):art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:e.message})},"json")}return!1}),$("#user_table_div").on("click",".user_edit_btn",function(){if(is_user_edit_status())return!1;var t=$(this).closest(".user_record");t.addClass("user_edit_status"),t.find("input").removeAttr("disabled"),t.find(".u_username").attr("disabled","disabled"),t.find("select").removeAttr("disabled");var e=$.trim(t.find(".u_username").val()),r=$.trim(t.find(".u_chname").val()),a=$.trim(t.find(".u_phone").val()),i=$.trim(t.find(".u_role").val()),s=$.trim(t.find(".u_email").val());return t.find(".u_username").attr("placeholder",gettext("请输入用户名")),t.find(".u_chname").attr("placeholder",gettext("请输入中文名")),t.find(".u_phone").attr("placeholder",gettext("请输入手机号")),t.find(".u_email").attr("placeholder",gettext("请输入邮箱")),t.attr("data-old-username",e),t.attr("data-old-chname",r),t.attr("data-old-phone",a),t.attr("data-old-role",i),t.attr("data-old-email",s),!1}),$("#user_table_div").on("click",".user_cancel_btn",function(){var t=$(this).closest(".user_record");t.removeClass("user_edit_status"),t.find("input").attr("disabled","disabled"),t.find("select").attr("disabled","disabled"),t.find(".u_username").attr("placeholder","--"),t.find(".u_chname").attr("placeholder","--"),t.find(".u_phone").attr("placeholder","--"),t.find(".u_email").attr("placeholder","--");var e=t.attr("data-old-username"),r=t.attr("data-old-chname"),a=t.attr("data-old-phone"),i=t.attr("data-old-role"),s=t.attr("data-old-email");return e||r||a||s?(t.find(".u_username").val(e),t.find(".u_chname").val(r),t.find(".u_phone").val(a),t.find(".u_role").val(i),t.find(".u_email").val(s)):t.remove(),0==$("#user_table").find(".user_record").length&&$("#no_record_row").show(),!1}),$("#user_table_div").on("click",".user_del_btn",function(){var t=$(this).closest(".user_record"),e=t.attr("user_id"),r=t.find(".u_username").val();t.find(".u_chname").val();if(e){var a=site_url+"accounts/user/"+e+"/",i="
"+gettext("您确定删除该用户吗?")+"
"+gettext("用户名 : ")+r+"
";art.dialog({title:gettext("删除确认"),width:340,icon:"question",lock:!0,content:i,ok:function(){art.dialog({id:"bktips",width:300,icon:"warning",lock:!0,content:gettext("正在进行删除操作,请稍后...")}),$.ajax({url:a,type:"DELETE",success:function(e){art.dialog({id:"bktips"}).close(),e.result?(art.dialog({id:"bktips",width:300,icon:"succeed",lock:!0,content:e.message}).time(2),t.remove(),get_all_users(1)):art.dialog({id:"bktips",width:300,icon:"error",lock:!0,content:e.message})},dataType:"json"})},cancel:function(){},okVal:gettext("确认删除"),cancelVal:gettext("取消")})}}),$("#user_table_div").on("click",".user_rest_btn",function(){$(".error_tip").hide(),$(".password_input").val(""),$("#password_tip").text("");var t=$(this).closest(".user_record"),e=t.attr("user_id");t.find(".u_username").val();art.dialog({id:"bkpwd",title:gettext("重置密码"),lock:!0,width:505,content:$("#change_password_div").get(0),cancelVal:gettext("取消"),cancel:function(){},okVal:gettext("重置密码"),ok:function(){var t=!0;if($(".error_tip").hide(),$("#pattern_tip").css("color","black"),$(".password_input").each(function(){var e=$.trim($(this).val());return e?e.match(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[A-Za-z0-9!@#\$%\^\*\(\)-_\+=]{8,20}$/)||"password1"!=$(this).attr("name")?void 0:($("#pattern_tip").css("color","red"),$(this).focus(),t=!1,!1):($(this).next(".error_tip").show(),$(this).focus(),t=!1,!1)}),!t)return!1;var r=$.trim($("#id_password1").val()),a=$.trim($("#id_password2").val());if(r!=a&&($("#password_tip").text(gettext("两次输入的新密码不一致")),t=!1),!t)return!1;var i=site_url+"accounts/user/"+e+"/password/",s=!0;if($.ajax({url:i,type:"PUT",data:{new_password1:r,new_password2:a},success:function(t){t.result||($("#password_tip").text(t.message),s=!1)},dataType:"json",async:!1}),!s)return!1;art.dialog({width:300,icon:"succeed",lock:!0,content:gettext("密码重置成功")}).time(2)}})}); \ No newline at end of file diff --git a/paas-ce/paas/login/templates/bkaccount/base.html b/paas-ce/paas/login/templates/bkaccount/base.html index 975d4436f..6ca51bcde 100644 --- a/paas-ce/paas/login/templates/bkaccount/base.html +++ b/paas-ce/paas/login/templates/bkaccount/base.html @@ -58,9 +58,10 @@ {% endif %} - - {% if request.user.is_superuser %} - + {% if request.user.is_superuser %} + + {% else %} + {% endif %}
diff --git a/paas-ce/paas/login/templates/bkaccount/user_table.part b/paas-ce/paas/login/templates/bkaccount/user_table.part index b3adb947a..aee0f8966 100644 --- a/paas-ce/paas/login/templates/bkaccount/user_table.part +++ b/paas-ce/paas/login/templates/bkaccount/user_table.part @@ -46,14 +46,14 @@ - + {% else %} {% endif %} diff --git a/paas-ce/paas/login/templates/bkaccount/users.html b/paas-ce/paas/login/templates/bkaccount/users.html index 4881f9abd..7a38cc366 100644 --- a/paas-ce/paas/login/templates/bkaccount/users.html +++ b/paas-ce/paas/login/templates/bkaccount/users.html @@ -4,8 +4,8 @@ diff --git a/paas-ce/paas/paas/account/backends.py b/paas-ce/paas/paas/account/backends.py index 339c70669..042c8cf3e 100644 --- a/paas-ce/paas/paas/account/backends.py +++ b/paas-ce/paas/paas/account/backends.py @@ -23,7 +23,12 @@ class BkBackend(ModelBackend): """ def authenticate(self, request): - is_login, username = is_bk_token_valid(request) + try: + is_login, username = is_bk_token_valid(request) + except Exception: + logger.exception("is_bk_token_valid raise exception") + return None + if not is_login: return None diff --git a/paas-ce/paas/paas/api/constants.py b/paas-ce/paas/paas/api/constants.py index 61d809af3..c4cca2999 100644 --- a/paas-ce/paas/paas/api/constants.py +++ b/paas-ce/paas/paas/api/constants.py @@ -20,3 +20,10 @@ class ApiErrorCodeEnumV2(Enum): ESB_NOT_VALID = 1301103 APP_NOT_EXIST = 1301104 NO_PERMISSION = 1301105 + + +class LightAppAPIActionEnum(Enum): + POST = "post" + PUT = "put" + DELETE = "delete" + PUT_LOGO = "put_logo" diff --git a/paas-ce/paas/paas/api/forms.py b/paas-ce/paas/paas/api/forms.py new file mode 100644 index 000000000..d1e24cebf --- /dev/null +++ b/paas-ce/paas/paas/api/forms.py @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. +Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at +http://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +""" # noqa + +from __future__ import unicode_literals +import urlparse + +from django import forms +from django.conf import settings + +from common.log import logger +from home.models import UsefulLinks +from app.models import App + + +class LightAppBaseForm(forms.Form): + def validate_light_app_name(self, name, old_name): + """ + 校验app名称 + """ + if len(name) > 20: + return False, "应用名称长度不能超过20个字符" + + query = UsefulLinks.objects.filter(name=name) + if old_name: + query = query.exclude(name=old_name) + if query.exists(): + return False, "应用名称[{}]已存在".format(name) + return True, "校验通过" + + def validate_app_url(self, url): + """ + 判断url是否在当前域名下 + """ + try: + url_pares = urlparse.urlparse(url) + hostname = url_pares.hostname + paas_domain = settings.PAAS_DOMAIN.split(":")[0] if settings.PAAS_DOMAIN else '' + if not hostname or hostname == paas_domain: + return True, '' + return False, "APP链接不合法,链接不在当前域名下" + except Exception as e: + logger.error("获取url的域名出错:%s, url:%s" % (e, url)) + return False, "校验APP链接异常" + + +class LightAppChangeBaseInfoForm(LightAppBaseForm): + bk_light_app_code = forms.CharField() + + def clean_bk_light_app_code(self): + bk_light_app_code = self.cleaned_data["bk_light_app_code"] + light_app = UsefulLinks.objects.get_light_app_or_none(bk_light_app_code) + if not light_app: + self.add_error("bk_light_app_code", "轻应用不存在") + + return bk_light_app_code + + +class LightAppCreateForm(LightAppBaseForm): + bk_app_code = forms.CharField() + bk_light_app_name = forms.CharField() + app_url = forms.CharField() + introduction = forms.CharField(required=False) + + def clean_bk_app_code(self): + bk_app_code = self.cleaned_data["bk_app_code"] + if not App.objects.filter(code=bk_app_code).exists(): + self.add_error('bk_app_code', "应用(%s)不存在" % bk_app_code) + + return bk_app_code + + def clean_bk_light_app_name(self): + bk_light_app_name = self.cleaned_data["bk_light_app_name"] + # for create, the old_name is '' + valid, message = self.validate_light_app_name(bk_light_app_name, '') + if not valid: + self.add_error('bk_light_app_name', message) + + return bk_light_app_name + + def clean_app_url(self): + app_url = self.cleaned_data['app_url'] + if not app_url: + self.add_error("app_url", "APP链接不能为空") + else: + valid, message = self.validate_app_url(app_url) + if not valid: + self.add_error("app_url", message) + + return app_url + + +class LightAppEditForm(LightAppChangeBaseInfoForm): + bk_light_app_name = forms.CharField(required=False) + app_url = forms.CharField(required=False) + introduction = forms.CharField(required=False) + + def clean_bk_light_app_name(self): + bk_light_app_name = self.cleaned_data["bk_light_app_name"] + if bk_light_app_name: + bk_light_app_code = self.cleaned_data.get('bk_light_app_code') + light_app = UsefulLinks.objects.get_light_app_or_none(bk_light_app_code) + if light_app: + old_app_name = light_app.name + valid, message = self.validate_light_app_name(bk_light_app_name, old_app_name) + if not valid: + self.add_error('bk_light_app_name', message) + + return bk_light_app_name + + def clean_app_url(self): + app_url = self.cleaned_data['app_url'] + valid, message = self.validate_app_url(app_url) + if not valid: + self.add_error("app_url", message) + + return app_url + + +class LightAppLogoModifyForm(LightAppChangeBaseInfoForm): + logo = forms.CharField() + + def clean_logo(self): + logo = self.cleaned_data['logo'] + if not logo: + self.add_error("logo", "logo 不允许为空") + + return logo diff --git a/paas-ce/paas/paas/api/response.py b/paas-ce/paas/paas/api/response.py new file mode 100644 index 000000000..df718d385 --- /dev/null +++ b/paas-ce/paas/paas/api/response.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. +Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at +http://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +""" # noqa + +from __future__ import unicode_literals + +from django.http import JsonResponse + +from api.constants import ApiErrorCodeEnumV2 + + +class ApiV2BaseJsonResponse(JsonResponse): + def __init__(self, result, code, message, data=None): + data = data if data is not None else {} + json_data = {'result': result, 'bk_error_code': code, 'bk_error_msg': message, 'data': data} + super(ApiV2BaseJsonResponse, self).__init__(json_data) + + +class ApiV2FailJsonResponse(ApiV2BaseJsonResponse): + def __init__(self, message, **kwargs): + code = kwargs.get('code') or ApiErrorCodeEnumV2.PARAM_NOT_VALID.value + data = kwargs.get('data') + super(ApiV2FailJsonResponse, self).__init__(False, code, message, data=data) + + +class ApiV2OKJsonResponse(ApiV2BaseJsonResponse): + def __init__(self, message, **kwargs): + data = kwargs.get('data') + super(ApiV2OKJsonResponse, self).__init__(True, ApiErrorCodeEnumV2.SUCCESS.value, message, data=data) diff --git a/paas-ce/paas/paas/api/urls.py b/paas-ce/paas/paas/api/urls.py index dbea747e7..59bfafefa 100644 --- a/paas-ce/paas/paas/api/urls.py +++ b/paas-ce/paas/paas/api/urls.py @@ -12,7 +12,7 @@ from django.conf.urls import url from api import views - +from api.constants import LightAppAPIActionEnum urlpatterns = [ # 应用基本信息API(已接入ESB) @@ -23,4 +23,10 @@ # after format url(r'^v2/app/info/$', views.AppInfoV2APIView.as_view()), + # 轻应用API(已接入ESB) + url(r'^v2/create_app/$', views.LightAppView.as_view(action=LightAppAPIActionEnum.POST.value)), + url(r'^v2/edit_app/$', views.LightAppView.as_view(action=LightAppAPIActionEnum.PUT.value)), + url(r'^v2/del_app/$', views.LightAppView.as_view(action=LightAppAPIActionEnum.DELETE.value)), + url(r'^v2/modify_app_logo/$', views.LightAppView.as_view(action=LightAppAPIActionEnum.PUT_LOGO.value)), + ] diff --git a/paas-ce/paas/paas/api/utils.py b/paas-ce/paas/paas/api/utils.py new file mode 100644 index 000000000..30edf863c --- /dev/null +++ b/paas-ce/paas/paas/api/utils.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. +Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at +http://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +""" # noqa + +from __future__ import unicode_literals +import base64 +import uuid + +from django.core.files.base import ContentFile + + +def trans_b64_to_content_file(value): + image_data = base64.b64decode(value) + image_name = ''.join([str(uuid.uuid4()), '.png']) + return ContentFile(image_data, image_name) diff --git a/paas-ce/paas/paas/api/views.py b/paas-ce/paas/paas/api/views.py index 52ae44afe..345b92fd7 100644 --- a/paas-ce/paas/paas/api/views.py +++ b/paas-ce/paas/paas/api/views.py @@ -8,6 +8,7 @@ """ # noqa from __future__ import unicode_literals +import json from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt @@ -15,9 +16,18 @@ from django.http import JsonResponse from account.decorators import login_exempt +from common.utils import first_error_message +from common.log import logger +from common.responses import OKJsonResponse from api.decorators import esb_required, esb_required_v2 +from api.response import ApiV2FailJsonResponse, ApiV2OKJsonResponse +from api.constants import ApiErrorCodeEnumV2 from app.models import App -from common.responses import OKJsonResponse +from home.models import UsefulLinks +from home.constants import LinkTypeEnum +from api.forms import (LightAppCreateForm, LightAppEditForm, + LightAppChangeBaseInfoForm, LightAppLogoModifyForm) +from api.utils import trans_b64_to_content_file class AppInfoAPIView(View): @@ -93,7 +103,8 @@ def get(self, request): if app_codes: app_code_list = app_codes.split(';') query = query.filter(code__in=app_code_list) - extra_fields_set = set(fields.split(';')) & set(['introduction', 'creator', 'developer']) if fields else set() + support_fields = ['introduction', 'creator', 'developer', 'tag'] + extra_fields_set = set(fields.split(';')) & set(support_fields) if fields else set() # 按照创建时间逆排序 query = query.order_by('-created_date') @@ -109,6 +120,12 @@ def get(self, request): item.update({'creator': app.creater}) if 'developer' in extra_fields_set: item.update({'developer': app.developer_str}) + if 'tag' in extra_fields_set: + if app.tags: + item.update({'tag': app.tags.to_dict()}) + else: + item.update({'tag': {}}) + app_list.append(item) return JsonResponse({ @@ -116,3 +133,91 @@ def get(self, request): "bk_error_code": 0, "data": app_list }) + + +class LightAppView(View): + action = "" + request_body_params = {} + + @method_decorator(csrf_exempt) + @method_decorator(login_exempt) + @method_decorator(esb_required_v2) + def dispatch(self, request, *args, **kwargs): + if request.method.lower() in self.http_method_names: + self.request_body_params = self._get_body_params(request) + handler = getattr(self, self.action, self.http_method_not_allowed) + else: + handler = self.http_method_not_allowed + return handler(request, *args, **kwargs) + + def _get_body_params(self, request): + try: + return json.loads(request.body) if request.body else {} + except Exception: + return {} + + def post(self, request, *args, **kwargs): + form = LightAppCreateForm(self.request_body_params) + if not form.is_valid(): + message = first_error_message(form) + return ApiV2FailJsonResponse(message, code=ApiErrorCodeEnumV2.PARAM_NOT_VALID.value) + + parent_app = App.objects.get(code=form.cleaned_data["bk_app_code"]) + + # 保存应用信息到数据库 + link = UsefulLinks.objects.create( + name=form.cleaned_data["bk_light_app_name"], + link=form.cleaned_data["app_url"], + link_type=LinkTypeEnum.LIGHT_APP.value, + introduction=form.cleaned_data["introduction"] or parent_app.introduction + ) + data = {'bk_light_app_code': link.code} + + return ApiV2OKJsonResponse("创建轻应用成功", data=data) + + def put(self, request, *args, **kwargs): + form = LightAppEditForm(self.request_body_params) + if not form.is_valid(): + message = first_error_message(form) + return ApiV2FailJsonResponse(message, code=ApiErrorCodeEnumV2.PARAM_NOT_VALID.value) + + light_app = UsefulLinks.objects.get_light_app_or_none(form.cleaned_data["bk_light_app_code"]) + + # 保存应用基本信息 + light_app.introduction = form.cleaned_data["introduction"] or light_app.introduction + light_app.name = form.cleaned_data["bk_light_app_name"] or light_app.name + light_app.link = form.cleaned_data["app_url"] or light_app.link + light_app.save() + + return ApiV2OKJsonResponse("app 修改成功", data={}) + + def put_logo(self, request, *args, **kwargs): + form = LightAppLogoModifyForm(self.request_body_params) + if not form.is_valid(): + message = first_error_message(form) + return ApiV2FailJsonResponse(message, code=ApiErrorCodeEnumV2.PARAM_NOT_VALID.value) + + light_app = UsefulLinks.objects.get_light_app_or_none(form.cleaned_data["bk_light_app_code"]) + + try: + light_app.logo = trans_b64_to_content_file(form.cleaned_data["logo"]) + light_app.save() + except Exception as e: + # 保存logo时出错 + logger.exception(u"save app logo fail: %s" % e) + return ApiV2FailJsonResponse("logo 数据格式不合法", code=ApiErrorCodeEnumV2.PARAM_NOT_VALID.value) + + return ApiV2OKJsonResponse("app logo修改成功", data={}) + + def delete(self, request, *args, **kwargs): + form = LightAppChangeBaseInfoForm(self.request_body_params) + if not form.is_valid(): + message = first_error_message(form) + return ApiV2FailJsonResponse(message, code=ApiErrorCodeEnumV2.PARAM_NOT_VALID.value) + + light_app = UsefulLinks.objects.get_light_app_or_none(form.cleaned_data["bk_light_app_code"]) + + # 将app状态标记为下架 + light_app.is_active = False + light_app.save() + return ApiV2OKJsonResponse("app 下架成功", data={}) diff --git a/paas-ce/paas/paas/app/constants.py b/paas-ce/paas/paas/app/constants.py index bfa1ca147..d9a87b8c5 100644 --- a/paas-ce/paas/paas/app/constants.py +++ b/paas-ce/paas/paas/app/constants.py @@ -82,3 +82,6 @@ class DBTypeEnum(Enum): (DBTypeEnum.SQLSERVER.value, 'SQL Server'), ] DB_TYPE_VALID_VALUES = dict(DB_TYPE_CHOICES).keys() + +# app desktop info +DESKTOP_DEFAULT_APP_IS_DISPLAY = True diff --git a/paas-ce/paas/paas/app/forms.py b/paas-ce/paas/paas/app/forms.py index 0d303a831..6a876a1a7 100644 --- a/paas-ce/paas/paas/app/forms.py +++ b/paas-ce/paas/paas/app/forms.py @@ -102,7 +102,7 @@ def clean_vcs_password(self): class AppQueryForm(forms.Form): keyword = forms.CharField(required=False) - hide_offline = forms.IntegerField(initial=0) + hide_offline = forms.CharField(initial="0") page = forms.IntegerField(required=False, initial=1) page_size = forms.IntegerField(required=False) @@ -110,6 +110,13 @@ def clean_keyword(self): keyword = self.cleaned_data["keyword"] return keyword.replace(' ', ' ').strip() + def clean_hide_offline(self): + try: + hide_offline = int(self.cleaned_data["hide_offline"]) + return hide_offline + except Exception: + return 0 + def clean_page_size(self): page_size = self.cleaned_data["page_size"] if not page_size: diff --git a/paas-ce/paas/paas/app/manager.py b/paas-ce/paas/paas/app/manager.py index d42b7c0cc..34aade49a 100644 --- a/paas-ce/paas/paas/app/manager.py +++ b/paas-ce/paas/paas/app/manager.py @@ -12,7 +12,7 @@ from django.db.models import Q from django.db import models -from app.constants import AppStateEnum +from app.constants import AppStateEnum, DESKTOP_DEFAULT_APP_IS_DISPLAY class AppManager(models.Manager): @@ -103,3 +103,14 @@ def exists(self, app_code): if not info: return False return True + + +class DesktopSettingsManager(models.Manager): + def is_app_display(self, app_code): + # if is useful links + if app_code.startswith("_"): + return True + + if not self.filter(app_code=app_code).exists(): + return DESKTOP_DEFAULT_APP_IS_DISPLAY + return self.get(app_code=app_code).is_display diff --git a/paas-ce/paas/paas/app/migrations/0008_auto_20190124_1708.py b/paas-ce/paas/paas/app/migrations/0008_auto_20190124_1708.py new file mode 100644 index 000000000..bf111d693 --- /dev/null +++ b/paas-ce/paas/paas/app/migrations/0008_auto_20190124_1708.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('app', '0007_auto_20161111_1348'), + ] + + operations = [ + migrations.CreateModel( + name='DesktopSettings', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('app_code', models.CharField(unique=True, max_length=30, verbose_name='\u5bf9\u5e94\u7684appcode')), + ('is_display', models.BooleanField(default=True, verbose_name='\u662f\u5426\u5728\u684c\u9762\u5c55\u793a')), + ], + options={ + 'db_table': 'paas_app_desktop_settings', + 'verbose_name': '\u5e94\u7528\u684c\u9762\u5c5e\u6027', + 'verbose_name_plural': '\u5e94\u7528\u684c\u9762\u5c5e\u6027', + }, + ), + migrations.AlterField( + model_name='app', + name='is_saas', + field=models.BooleanField(default=False, help_text='SaaS\u670d\u52a1\uff0c\u5373\u901a\u8fc7\u76f4\u63a5\u4e0a\u4f20\u5305\u90e8\u7f72', verbose_name='\u662f\u5426\u4e3aSaaS\u670d\u52a1'), + ), + migrations.AlterField( + model_name='secureinfo', + name='vcs_type', + field=models.SmallIntegerField(default=1, help_text='\u7248\u672c\u4ed3\u5e93\u7c7b\u578b', verbose_name='\u7248\u672c\u63a7\u5236\u7c7b\u578b', choices=[(0, 'Git'), (1, 'SVN')]), + ), + ] diff --git a/paas-ce/paas/paas/app/models.py b/paas-ce/paas/paas/app/models.py index ea55baad3..a53fd3dfa 100644 --- a/paas-ce/paas/paas/app/models.py +++ b/paas-ce/paas/paas/app/models.py @@ -18,7 +18,7 @@ from app.constants import (DB_TYPE_CHOICES, LANGUAGE_CHOICES, STATE_CHOICES, STATE_CHOICES_DISPALY_DICT, VCS_TYPE_CHOICES, AppStateEnum, LanguageEnum, VCSTypeEnum, DBTypeEnum) -from app.manager import AppManager, SecureInfoManager +from app.manager import AppManager, SecureInfoManager, DesktopSettingsManager from common.utils import should_update_logo, get_app_logo from common.constants import LogoImgRelatedDirEnum @@ -48,6 +48,12 @@ class Meta: verbose_name = "应用分类信息" verbose_name_plural = "应用分类信息" + def to_dict(self): + return { + "name": self.name, + "code": self.code, + } + class App(models.Model): """ @@ -259,3 +265,20 @@ class Meta: db_table = 'paas_app_secureinfo' verbose_name = "应用安全相关信息" verbose_name_plural = "应用安全相关信息" + + +class DesktopSettings(models.Model): + """应用桌面属性 + """ + app_code = models.CharField("对应的appcode", max_length=30, unique=True) + is_display = models.BooleanField("是否在桌面展示", default=True) + + objects = DesktopSettingsManager() + + def __unicode__(self): + return self.app_code + + class Meta: + db_table = 'paas_app_desktop_settings' + verbose_name = "应用桌面属性" + verbose_name_plural = "应用桌面属性" diff --git a/paas-ce/paas/paas/app_env/admin.py b/paas-ce/paas/paas/app_env/admin.py index 8e3d4ac9f..965b1780d 100644 --- a/paas-ce/paas/paas/app_env/admin.py +++ b/paas-ce/paas/paas/app_env/admin.py @@ -6,6 +6,19 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa -# from django.contrib import admin -# Register your models here. +from __future__ import unicode_literals + +from django.contrib import admin + +from app_env.models import AppEnvVar + + +class AppEnvVarAdmin(admin.ModelAdmin): + + list_display = ('app_code', 'mode', 'name', 'value', 'intro') + search_fields = ('name', 'value', 'intro') + list_filter = ('app_code', 'mode') + + +admin.site.register(AppEnvVar, AppEnvVarAdmin) diff --git a/paas-ce/paas/paas/app_env/forms.py b/paas-ce/paas/paas/app_env/forms.py index 0fbbf9e3b..3786fa73e 100644 --- a/paas-ce/paas/paas/app_env/forms.py +++ b/paas-ce/paas/paas/app_env/forms.py @@ -20,8 +20,8 @@ class AppEnvForm(forms.Form): name = forms.CharField(max_length=44, error_messages={"required": "变量名不能为空!", "max_length": "变量名不能超过50个字符!"}, validators=[RegexValidator(r'^[a-zA-Z0-9_]+$', message="请输入合法的变量名, 只允许字母数字下划线!")]) - value = forms.CharField(max_length=100, error_messages={ - "required": "变量名不能为空!", + value = forms.CharField(max_length=1000, error_messages={ + "required": "变量值不能为空!", "max_length": "变量值不能超过1000个字符!" }) intro = forms.CharField() diff --git a/paas-ce/paas/paas/app_env/manager.py b/paas-ce/paas/paas/app_env/manager.py index 70235912f..9c56291bc 100644 --- a/paas-ce/paas/paas/app_env/manager.py +++ b/paas-ce/paas/paas/app_env/manager.py @@ -10,6 +10,8 @@ from django.db import models from common.constants import ModeEnum +from common.log import logger +from app_env.utils import validate_env_var class AppEnvVarManager(models.Manager): @@ -22,6 +24,39 @@ def get_env_vars(self, app_code, mode): return {} return {env_var.name: env_var.value for env_var in env_vars} + def add_env_vars(self, app_code, env_var_list): + """ + for ModeEnum.All.value only + env_var_list = [{key: hello, value: world}] + """ + if not env_var_list: + return + + for env in env_var_list: + key = env.get("key") + value = env.get("value") + if (not key) or (value is None): + continue + + key = str(key) + value = str(value) + is_valid, message = validate_env_var(key, value) + if not is_valid: + logger.error("App: %s [key=%s, value=%s] invalid, %s", app_code, key, value, message) + continue + + self._add_or_update_env_var_mode_all(app_code, key, value) + + def _add_or_update_env_var_mode_all(self, app_code, name, value): + if self.filter(app_code=app_code, mode=ModeEnum.ALL, name=name).exists(): + env_var = self.get(app_code=app_code, mode=ModeEnum.ALL, name=name) + env_var.value = value + env_var.save() + else: + self.filter(app_code=app_code, mode__in=(ModeEnum.PROD, ModeEnum.TEST), name=name).delete() + env_var = self.create(app_code=app_code, mode=ModeEnum.ALL, name=name, + value=value, intro="set by S-mart App") + def _gen_extra_modes(self, mode): extra_modes = ([mode, ModeEnum.ALL.value] if mode in (ModeEnum.TEST.value, ModeEnum.PROD.value) else [ModeEnum.ALL.value, ModeEnum.TEST.value, ModeEnum.PROD.value]) diff --git a/paas-ce/paas/paas/app_env/utils.py b/paas-ce/paas/paas/app_env/utils.py new file mode 100644 index 000000000..6eca69480 --- /dev/null +++ b/paas-ce/paas/paas/app_env/utils.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. +Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at +http://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +""" # noqa + +from __future__ import unicode_literals + +import re + + +def _validate_env_var_name(name): + if not name: + return False, "变量名不能为空!" + + if not name.startswith("BKAPP_"): + return False, "变量名必须以BKAPP_开头" + + check_result = re.match(r'^[a-zA-Z0-9_]+$', name) + if not check_result or len(name) > 50: + return False, "请输入合法的变量名, 只允许字母数字下划线!" + + return True, None + + +def _validate_env_var_value(value): + if value is None or value == "": + return False, "变量值不能为空!" + if len(value) > 1000: + return False, "变量值不能超过1000个字符!" + + if '"' in value: + return False, "变量值不能包含引号!" + return True, None + + +def validate_env_var(name, value): + is_valid, message = _validate_env_var_name(name) + if not is_valid: + return False, message + is_valid, message = _validate_env_var_value(value) + if not is_valid: + return False, message + + return True, 'valid' diff --git a/paas-ce/paas/paas/common/utils.py b/paas-ce/paas/paas/common/utils.py index 901bec9bb..dbd9adf38 100644 --- a/paas-ce/paas/paas/common/utils.py +++ b/paas-ce/paas/paas/common/utils.py @@ -46,14 +46,14 @@ def should_update_logo(app_code, app_logo_name): # if cmp(logo_name, app_logo_name): if logo_name != app_logo_name: # logo_name = LogoImgRelatedDirEnum.APP.value + '/' + str(app_code) + logo_ext - _delete_exist_logo_file(logo_name) + delete_exist_logo_file(logo_name) # 指定图片名称 # self.logo.name = LogoImgRelatedDirEnum.APP.value + '/' + str(app_code) + logo_ext return True, logo_name return False, None -def _delete_exist_logo_file(name): +def delete_exist_logo_file(name): _file = os.path.join(settings.MEDIA_ROOT, name) if os.path.exists(_file): os.remove(_file) diff --git a/paas-ce/paas/paas/esb/apps/api_docs/api_views.py b/paas-ce/paas/paas/esb/apps/api_docs/api_views.py index a786be2e5..cb5eadfec 100644 --- a/paas-ce/paas/paas/esb/apps/api_docs/api_views.py +++ b/paas-ce/paas/paas/esb/apps/api_docs/api_views.py @@ -6,9 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - -from __future__ import unicode_literals - from django.views.generic import View from django.http import Http404 from django.db.models import Q @@ -110,7 +107,7 @@ def post(self, request): operator=request.user.username, board='', component_id=data['api_id'], - content=data.get('content', _("满足需求")), + content=data.get('content', _(u"满足需求")), ).save() return JsonResponse({'result': True}) diff --git a/paas-ce/paas/paas/esb/apps/api_docs/urls.py b/paas-ce/paas/paas/esb/apps/api_docs/urls.py index eeaf5e43d..0fe5ad2b9 100644 --- a/paas-ce/paas/paas/esb/apps/api_docs/urls.py +++ b/paas-ce/paas/paas/esb/apps/api_docs/urls.py @@ -6,7 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - from django.conf.urls import url from . import views, api_views diff --git a/paas-ce/paas/paas/esb/apps/api_docs/utils.py b/paas-ce/paas/paas/esb/apps/api_docs/utils.py index d776fabb7..154f449a0 100644 --- a/paas-ce/paas/paas/esb/apps/api_docs/utils.py +++ b/paas-ce/paas/paas/esb/apps/api_docs/utils.py @@ -6,7 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - from esb.bkcore.models import ComponentSystem diff --git a/paas-ce/paas/paas/esb/apps/api_docs/views.py b/paas-ce/paas/paas/esb/apps/api_docs/views.py index 80276ed68..84c6cd6d9 100644 --- a/paas-ce/paas/paas/esb/apps/api_docs/views.py +++ b/paas-ce/paas/paas/esb/apps/api_docs/views.py @@ -6,7 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - from django.views.generic import View from django.shortcuts import render from django.http import Http404 diff --git a/paas-ce/paas/paas/esb/apps/bootstrapform/configs.py b/paas-ce/paas/paas/esb/apps/bootstrapform/configs.py index 463aba84f..7a5d71434 100644 --- a/paas-ce/paas/paas/esb/apps/bootstrapform/configs.py +++ b/paas-ce/paas/paas/esb/apps/bootstrapform/configs.py @@ -6,7 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - from django.conf import settings diff --git a/paas-ce/paas/paas/esb/apps/bootstrapform/templatetags/bootstrap.py b/paas-ce/paas/paas/esb/apps/bootstrapform/templatetags/bootstrap.py index 2ef01bb68..c7444d7cf 100644 --- a/paas-ce/paas/paas/esb/apps/bootstrapform/templatetags/bootstrap.py +++ b/paas-ce/paas/paas/esb/apps/bootstrapform/templatetags/bootstrap.py @@ -6,7 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - from django import forms, VERSION as DJANGO_VERSION from django.template import Context from django.template.loader import get_template diff --git a/paas-ce/paas/paas/esb/apps/guide/component_template/en/hcp/get_host_list.py b/paas-ce/paas/paas/esb/apps/guide/component_template/en/hcp/get_host_list.py index 6525a7237..3924440a2 100644 --- a/paas-ce/paas/paas/esb/apps/guide/component_template/en/hcp/get_host_list.py +++ b/paas-ce/paas/paas/esb/apps/guide/component_template/en/hcp/get_host_list.py @@ -6,7 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - import json from django import forms diff --git a/paas-ce/paas/paas/esb/apps/guide/component_template/en/hcp/toolkit/configs.py b/paas-ce/paas/paas/esb/apps/guide/component_template/en/hcp/toolkit/configs.py index bb5f109f9..08de399c2 100644 --- a/paas-ce/paas/paas/esb/apps/guide/component_template/en/hcp/toolkit/configs.py +++ b/paas-ce/paas/paas/esb/apps/guide/component_template/en/hcp/toolkit/configs.py @@ -6,7 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - from esb.utils import SmartHost diff --git a/paas-ce/paas/paas/esb/apps/guide/component_template/zh-hans/hcp/get_host_list.py b/paas-ce/paas/paas/esb/apps/guide/component_template/zh-hans/hcp/get_host_list.py index 90300f396..7d9be3316 100644 --- a/paas-ce/paas/paas/esb/apps/guide/component_template/zh-hans/hcp/get_host_list.py +++ b/paas-ce/paas/paas/esb/apps/guide/component_template/zh-hans/hcp/get_host_list.py @@ -6,7 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - import json from django import forms diff --git a/paas-ce/paas/paas/esb/apps/guide/component_template/zh-hans/hcp/toolkit/configs.py b/paas-ce/paas/paas/esb/apps/guide/component_template/zh-hans/hcp/toolkit/configs.py index 86dae674b..f1151acae 100644 --- a/paas-ce/paas/paas/esb/apps/guide/component_template/zh-hans/hcp/toolkit/configs.py +++ b/paas-ce/paas/paas/esb/apps/guide/component_template/zh-hans/hcp/toolkit/configs.py @@ -6,7 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - from esb.utils import SmartHost diff --git a/paas-ce/paas/paas/esb/apps/guide/mdfiles/zh-hans/weixin_component_guide.md b/paas-ce/paas/paas/esb/apps/guide/mdfiles/zh-hans/weixin_component_guide.md index 66cdc014a..5b2942f82 100644 --- a/paas-ce/paas/paas/esb/apps/guide/mdfiles/zh-hans/weixin_component_guide.md +++ b/paas-ce/paas/paas/esb/apps/guide/mdfiles/zh-hans/weixin_component_guide.md @@ -1,11 +1,10 @@ # 微信消息组件 -> 蓝鲸微信消息可通过微信公众号,微信企业号或者企业微信三种方式进行通知, -> 在配置前请先阅读三种方式的差异性,再选择其中一种方式进行配置 +> 蓝鲸微信消息可通过微信公众号或者企业微信2种方式进行通知, +> 在配置前请先阅读2种方式的差异性,再选择其中一种方式进行配置 |
通知方式
| 用户绑定 | open_paas模块所在服务器配置 |
微信公众平台配置
| | --- | --- | --- | --- | | 微信公众号 | 用户客户端需要有外网或者至少能访问微信相关链接 | (1)必须要有外网或者能访问微信提供的API
(2)需要反向代理,能够让代理转发到http://\{paas_domain\}/console/user_center/weixin/mp/callback/| (1)服务器配置
(2)消息模板配置 | -| 微信企业号 | 用户客户端需要有外网或者至少能访问微信相关链接 | 必须要有外网或者能访问微信提供的API | 可信任域名配置 | | 企业微信 | 用户客户端需要有外网或者至少能访问微信相关链接 | 必须要有外网或者能访问微信提供的API | 授权回调域配置 | ### 前提准备 @@ -15,7 +14,7 @@ # 微信提供的API 协议均为https # 微信公众号 api.weixin.qq.com -# 微信企业号/ 企业微信 +# 企业微信 qyapi.weixin.qq.com ``` @@ -25,13 +24,6 @@ qyapi.weixin.qq.com # 微信提供的API 协议均为https # 微信公众号 mp.weixin.qq.com -# 微信企业号 -qy.weixin.qq.com -open.weixin.qq.com -res.wx.qq.com -rescdn.qqmail.com -long.open.weixin.qq.com -wx.qlogo.cn # 企业微信 open.work.weixin.qq.com rescdn.qqmail.com @@ -40,7 +32,7 @@ js.aq.qq.com ### 入口说明 * 微信公众号: https://mp.weixin.qq.com/ -* 微信企业号/企业微信:https://work.weixin.qq.com/ +* 企业微信:https://work.weixin.qq.com/ * 蓝鲸微信组件配置入口:http://{paas_domain}/esb/manager/index/, 通道管理 → 找到通道名称为“发送微信消息”的组件 → 组件配置 * 蓝鲸用户微信绑定入口: http://{paas_domain}, 个人中心 → 微信绑定 @@ -66,17 +58,20 @@ js.aq.qq.com * 若已经添加模块库或者已经搜索到“蓝鲸消息通知”的模板库,点击详情进入该模板并添加该模板,添加后在“功能 → 模板消息 → 我的模板”中将看到添加的消息模板,其中的模版ID是我们后续配置组件需要的 -#### 微信公众号 → 服务器配置 +#### 微信公众号 → IP白名单和服务器配置 > 请先在微信公众平台上查看公众号后台 → 开发 → 基本配置,是否已经配置了服务器配置(服务器地址,令牌,消息加解密密钥,消息加解密方式)![](/static/esb/guide/weixin_component_guide/15081252708641.jpg) -##### 1. 微信公众平台上已配置了服务器配置 -联系配置了服务器配置的人员,请其协助将在服务器地址响应的服务中添加调用http://{paas_domain}/console/user_center/weixin/mp/callback/(透传微信事件推送) +##### 1. 基本配置 → IP白名单 +由于ESB发送微信消息需要调用微信获取AccessToken接口,所以需要在“基本配置 → 公众号开发者信息 → IP白名单”中配置蓝鲸PaaS部署的机器IP + +##### 2. 微信公众平台上已配置了服务器配置 +联系配置了服务器配置的人员,请其协助将在服务器地址响应的服务中添加调用http://{paas_domain}/console/user_center/weixin/mp/callback/(透传微信事件推送) (非80端口则paas_domain需带上端口,若是ssl,则需将http改为https) -##### 2. 微信公众平台上未配置服务器配置 +##### 3. 微信公众平台上未配置服务器配置 填写服务器配置(填写完,先不要点击提交) * url 填写外网能够访问到的URL(暂时称为weixin_server_url) -同时需要配置反向代理,将weixin_server_url 转发到企业蓝鲸平台http://{paas_domain}/console/user_center/weixin/mp/callback/ +同时需要配置反向代理,将weixin_server_url 转发到企业蓝鲸平台http://{paas_domain}/console/user_center/weixin/mp/callback/ (非80端口则paas_domain需带上端口,若是ssl,则需将http改为https) * Token 英文或数字,长度为3-32字符,请自行定义随机填写 * EncodingAESKey 点击随机生成即可 * 消息加解密方式,选择明文模式即可(任何一种模式都不影响) @@ -97,30 +92,7 @@ js.aq.qq.com 至此蓝鲸通过公众号发送消息的配置完成,请到最后一步用户绑定后验证配置是否正确 -### 二. 微信企业号 -#### 微信企业号配置 -* 配置用于蓝鲸消息通知的应用 - -“微信企业号 → 应用中心” 可以选择已经存在的消息型应用或者新建一个类型为消息型的应用,将应用的可见范围设置为全企业人员(或至少设置为可能需要接送微信消息通知的人员) - -* 配置登录授权域名 - -(1)“微信企业号 → 设置 → 权限管理” 新建普通管理组,将用于蓝鲸消息通知的应用添加到该普通管理组的应用权限中 - -(2)“微信企业号 → 设置 → 功能设置 → 登录授权” 在刚刚创建的普通管理组项设置可信域名为:{paas_domain} (该域名只需要企业内部能访问即可,不需要配置为外网域名) - -#### 蓝鲸平台 → API网关 -> 蓝鲸微信组件配置入口:http:/{paas_domain}/esb/manager/index/, 通道管理 → 找到通道名称为“发送微信消息”的组件 → 组件配置 -![](/static/esb/guide/weixin_component_guide/15081428561464.jpg) - -* wx_type 选择“微信企业号” -* wx_qy_corpid 【“微信企业号 → 设置 → 权限管理 → 对应的普通管理组“】CorpID -* wx_qy_corpsecret【“微信企业号 → 设置 → 权限管理 → 对应的普通管理组”】Secret -* wx_qy_agentid 【“微信企业号 → 应用中心 → 对应的应用】应用ID - -至此蓝鲸通过企业号发送消息的配置完成,请到最后一步用户绑定后验证配置是否正确 - -### 三. 企业微信 +### 二. 企业微信 #### 企业微信配置 * 配置用于蓝鲸消息通知的应用 @@ -129,7 +101,7 @@ js.aq.qq.com * 配置Web网页登录授权回调域 “企业微信 → 企业应用 → 选择对应的应用 → 企业微信授权登录 → 设置 → Web网页 - → 设置授权回调域” 设置{paas_domain}为登录授权回到域 + → 设置授权回调域” 设置{paas_domain}为登录授权回调域 (非80端口则paas_domain需带上端口) #### 蓝鲸平台 → API网关 > 蓝鲸微信组件配置入口:http:/{paas_domain}/esb/manager/index/, 通道管理 → 找到通道名称为“发送微信消息”的组件 → 组件配置 @@ -148,9 +120,7 @@ js.aq.qq.com 点击"绑定微信",扫描绑定即可 需要注意: -(1)若是企业号,需要用户提前关注企业号 - -(2)若是企业微信,需要用户用企业微信APP进行扫描 +(1)若是企业微信,需要用户用企业微信APP进行扫描 ### 其它注意项 * **组件会根据开发者ID和开发者密码,获取access_token发送模版消息等,业务若需集中管理 access_token,可优化 components/apis/weixin_mp/get_token.py 中 access_token 获取逻辑** @@ -159,6 +129,3 @@ js.aq.qq.com (1)用户客户端未能访问外网或无法访问微信相关URL (2)open_paas所在服务器服务访问外网或至少无法请求微信相关接口 - - - diff --git a/paas-ce/paas/paas/esb/apps/guide/urls.py b/paas-ce/paas/paas/esb/apps/guide/urls.py index 9281b8d93..2a5300348 100644 --- a/paas-ce/paas/paas/esb/apps/guide/urls.py +++ b/paas-ce/paas/paas/esb/apps/guide/urls.py @@ -6,7 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - from django.conf.urls import url from . import views diff --git a/paas-ce/paas/paas/esb/apps/guide/views.py b/paas-ce/paas/paas/esb/apps/guide/views.py index dfcc513e5..822a0176e 100644 --- a/paas-ce/paas/paas/esb/apps/guide/views.py +++ b/paas-ce/paas/paas/esb/apps/guide/views.py @@ -6,7 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - import copy import markdown from markdown.extensions.headerid import HeaderIdExtension diff --git a/paas-ce/paas/paas/esb/apps/manager/buffet_comp/api_views.py b/paas-ce/paas/paas/esb/apps/manager/buffet_comp/api_views.py index fadbb1342..ab4c5f186 100644 --- a/paas-ce/paas/paas/esb/apps/manager/buffet_comp/api_views.py +++ b/paas-ce/paas/paas/esb/apps/manager/buffet_comp/api_views.py @@ -6,10 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - -""" -Copyright © 2012-2017 Tencent BlueKing. All Rights Reserved. 蓝鲸智云 版权所有 -""" from django.views.generic import View from esb.bkcore.models import ESBBuffetMapping diff --git a/paas-ce/paas/paas/esb/apps/manager/buffet_comp/forms.py b/paas-ce/paas/paas/esb/apps/manager/buffet_comp/forms.py index 3766d4acf..97052158b 100644 --- a/paas-ce/paas/paas/esb/apps/manager/buffet_comp/forms.py +++ b/paas-ce/paas/paas/esb/apps/manager/buffet_comp/forms.py @@ -6,10 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - -""" -Copyright © 2012-2017 Tencent BlueKing. All Rights Reserved. 蓝鲸智云 版权所有 -""" from django import forms from django.utils.translation import ugettext as _ diff --git a/paas-ce/paas/paas/esb/apps/manager/buffet_comp/views.py b/paas-ce/paas/paas/esb/apps/manager/buffet_comp/views.py index 0b5800c01..1af99f696 100644 --- a/paas-ce/paas/paas/esb/apps/manager/buffet_comp/views.py +++ b/paas-ce/paas/paas/esb/apps/manager/buffet_comp/views.py @@ -6,10 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - -""" -Copyright © 2012-2017 Tencent BlueKing. All Rights Reserved. 蓝鲸智云 版权所有 -""" from django.shortcuts import render from django.views.generic import View from django.http import HttpResponseRedirect @@ -86,6 +82,7 @@ def get(self, request): schema_prefix = '%s://' % schema if not host.startswith(schema_prefix): host = '%s://%s' % (schema, host) + return render(request, 'manager/buffet_comp/list.html', { 'items': items, 'host': '%s/api/c/self-service-api' % host, diff --git a/paas-ce/paas/paas/esb/apps/manager/channel/api_views.py b/paas-ce/paas/paas/esb/apps/manager/channel/api_views.py index 709f2a26b..6320c0eb6 100644 --- a/paas-ce/paas/paas/esb/apps/manager/channel/api_views.py +++ b/paas-ce/paas/paas/esb/apps/manager/channel/api_views.py @@ -6,7 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - from django.views.generic import View from django.conf import settings diff --git a/paas-ce/paas/paas/esb/apps/manager/channel/forms.py b/paas-ce/paas/paas/esb/apps/manager/channel/forms.py index adf7e5a18..109fe904b 100644 --- a/paas-ce/paas/paas/esb/apps/manager/channel/forms.py +++ b/paas-ce/paas/paas/esb/apps/manager/channel/forms.py @@ -6,7 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - import re import json diff --git a/paas-ce/paas/paas/esb/apps/manager/channel/views.py b/paas-ce/paas/paas/esb/apps/manager/channel/views.py index 9700a00ff..2725309ae 100644 --- a/paas-ce/paas/paas/esb/apps/manager/channel/views.py +++ b/paas-ce/paas/paas/esb/apps/manager/channel/views.py @@ -6,7 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - import json from django.shortcuts import render @@ -14,8 +13,8 @@ from django.http import HttpResponseRedirect from django.views.generic import View from django.http import Http404 +from django.utils.translation import ugettext as _ -from common.log import logger from esb.bkcore.models import ESBChannel, ComponentSystem from esb.common.decorators import is_user_super from esb.common.django_utils import i18n_form, get_cur_language @@ -97,21 +96,9 @@ def get(self, request, channel_id): channel = ESBChannel.objects.get(id=channel_id) channel.name = channel.name_display - if channel.is_confapi: - # confapi 不更新 comp_conf - channel.comp_conf = None form = EditESBChannelForm(instance=channel) system_form = ComponentSystemForm() - try: - if channel.comp_conf: - comp_conf = json.loads(channel.comp_conf) - else: - comp_conf = None - except Exception: - logger.error('esb channel comp_conf is not json, channel_id: %s, comp_conf: %s', - channel_id, channel.comp_conf) - comp_conf = None try: rate_limit_conf = json.loads(channel.rate_limit_conf) @@ -122,11 +109,12 @@ def get(self, request, channel_id): rate_limit_tokens = '' rate_limit_unit = 'second' - _comp_conf_group = self.comp_conf_group(channel.path, comp_conf) - # 可在 comp_conf_group 中新增字段,用户在通道管理页面上可看到并更新新增字段 - if _comp_conf_group: + if channel.allow_edit_comp_conf: + # 可在 comp_conf_group 中新增字段,用户在通道管理页面上可看到并更新新增字段 + _comp_conf_group = self.comp_conf_group(channel.path, channel.comp_conf_json) _comp_conf_val = json.dumps([(conf['key'], conf['value']) for conf in _comp_conf_group['comp_conf']]) else: + _comp_conf_group = None _comp_conf_val = '' form = i18n_form(form) @@ -142,7 +130,6 @@ def get(self, request, channel_id): 'system_form': system_form, 'menu_items': menu_items, 'menu_active_item': menu_active_item, - 'comp_conf': comp_conf, 'comp_conf_val': _comp_conf_val, 'rate_limit_required': channel.rate_limit_required, 'comp_conf_group': _comp_conf_group, @@ -162,8 +149,9 @@ def post(self, request, channel_id): if channel.is_official: unchanged_data['name'] = channel.name if channel.is_confapi: - unchanged_data['comp_conf'] = channel.comp_conf unchanged_data['component_name'] = channel.component_name + if not channel.allow_edit_comp_conf: + unchanged_data['comp_conf'] = channel.comp_conf form = EditESBChannelForm(post_data, instance=channel) if form.is_valid(): @@ -184,8 +172,6 @@ def comp_conf_group(self, path, comp_conf): """ 注意:生成结果的 comp_conf 中不能有 key 值相同的项,否则,数据库中 comp_conf 也会出现多余的重复字段 """ - if not comp_conf: - return None if path == '/cmsi/send_weixin/': comp_conf = dict(comp_conf) return { @@ -193,8 +179,8 @@ def comp_conf_group(self, path, comp_conf): 'group_field': 'wx_type', # 参数分组可选值 'groups': [ - {'value': 'qywx', 'label': u'企业微信'}, - {'value': 'mp', 'label': u'微信公众号'}, + {'value': 'qywx', 'label': _(u'企业微信')}, + {'value': 'mp', 'label': _(u'微信公众号')}, ], # 字段配置 'comp_conf': [ @@ -282,7 +268,7 @@ def comp_conf_group(self, path, comp_conf): }, ] } - elif path == '/cmsi/send_sms/': + elif path in ['/cmsi/send_sms/', '/cmsi/send_voice_msg/']: comp_conf = dict(comp_conf) return { # 字段配置 diff --git a/paas-ce/paas/paas/esb/apps/manager/index/views.py b/paas-ce/paas/paas/esb/apps/manager/index/views.py index 5eee058a8..1a1771a3e 100644 --- a/paas-ce/paas/paas/esb/apps/manager/index/views.py +++ b/paas-ce/paas/paas/esb/apps/manager/index/views.py @@ -6,10 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - -""" -Copyright © 2012-2017 Tencent BlueKing. All Rights Reserved. 蓝鲸智云 版权所有 -""" from django.shortcuts import render from django.views.generic import View diff --git a/paas-ce/paas/paas/esb/apps/manager/system/api_views.py b/paas-ce/paas/paas/esb/apps/manager/system/api_views.py index 6fb23bfdc..775e54b53 100644 --- a/paas-ce/paas/paas/esb/apps/manager/system/api_views.py +++ b/paas-ce/paas/paas/esb/apps/manager/system/api_views.py @@ -6,7 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - from django.views.generic import View from django.utils.translation import ugettext as _ diff --git a/paas-ce/paas/paas/esb/apps/manager/system/forms.py b/paas-ce/paas/paas/esb/apps/manager/system/forms.py index a37dfad28..4af88cda5 100644 --- a/paas-ce/paas/paas/esb/apps/manager/system/forms.py +++ b/paas-ce/paas/paas/esb/apps/manager/system/forms.py @@ -6,7 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - from django import forms from django.utils.translation import ugettext as _ diff --git a/paas-ce/paas/paas/esb/apps/manager/system/views.py b/paas-ce/paas/paas/esb/apps/manager/system/views.py index 2b28349e8..5c865e939 100644 --- a/paas-ce/paas/paas/esb/apps/manager/system/views.py +++ b/paas-ce/paas/paas/esb/apps/manager/system/views.py @@ -6,10 +6,6 @@ http://opensource.org/licenses/MIT Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # noqa - -""" -Copyright © 2012-2017 Tencent BlueKing. All Rights Reserved. 蓝鲸智云 版权所有 -""" from django.shortcuts import render from django.core.urlresolvers import reverse from django.http import HttpResponseRedirect diff --git a/paas-ce/paas/paas/esb/apps/manager/templates/manager/buffet_comp/list.html b/paas-ce/paas/paas/esb/apps/manager/templates/manager/buffet_comp/list.html index 47f482440..8dd7b5af2 100644 --- a/paas-ce/paas/paas/esb/apps/manager/templates/manager/buffet_comp/list.html +++ b/paas-ce/paas/paas/esb/apps/manager/templates/manager/buffet_comp/list.html @@ -50,10 +50,10 @@ {{ item.created_time|date:"Y-m-d H:i" }} -