mirror of https://github.com/jumpserver/jumpserver
Merge branch 'v3' of github.com:jumpserver/jumpserver into v3
commit
7f6d13a5a6
|
@ -1,9 +1,6 @@
|
|||
from assets import serializers
|
||||
from assets.models import AccountTemplate
|
||||
from rbac.permissions import RBACPermission
|
||||
from authentication.const import ConfirmType
|
||||
from common.mixins import RecordViewLogMixin
|
||||
from common.permissions import UserConfirmation
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
|
||||
|
||||
|
|
|
@ -82,6 +82,10 @@ class Account(AbsConnectivity, BaseAccount):
|
|||
def __str__(self):
|
||||
return '{}'.format(self.username)
|
||||
|
||||
@lazyproperty
|
||||
def has_secret(self):
|
||||
return bool(self.secret)
|
||||
|
||||
@classmethod
|
||||
def get_manual_account(cls):
|
||||
""" @INPUT 手动登录的账号(any) """
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from assets.models import BaseAccount
|
||||
from assets.serializers.base import AuthValidateMixin
|
||||
|
@ -9,6 +10,8 @@ __all__ = ['BaseAccountSerializer']
|
|||
|
||||
|
||||
class BaseAccountSerializer(AuthValidateMixin, BulkOrgResourceModelSerializer):
|
||||
has_secret = serializers.BooleanField(label=_("Has secret"), read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = BaseAccount
|
||||
fields_mini = ['id', 'name', 'username']
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from common.drf.serializers import SecretReadableMixin
|
||||
from assets.models import AccountTemplate
|
||||
from common.drf.serializers import SecretReadableMixin
|
||||
from .base import BaseAccountSerializer
|
||||
|
||||
|
||||
|
|
|
@ -18,6 +18,23 @@
|
|||
|
||||
<style>
|
||||
.login-content {
|
||||
{#box-shadow: 0 5px 5px -3px rgb(0 0 0 / 15%), 0 8px 10px 1px rgb(0 0 0 / 14%), 0 3px 14px 2px rgb(0 0 0 / 12%);#}
|
||||
}
|
||||
|
||||
.login-footer {
|
||||
height: 50px;
|
||||
width: 1000px;
|
||||
margin: 40px auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer-item {
|
||||
padding: 5px 20px;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.footer-item a {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.help-block {
|
||||
|
@ -52,15 +69,15 @@
|
|||
}
|
||||
|
||||
.login-content {
|
||||
height: 490px;
|
||||
width: 1066px;
|
||||
height: 500px;
|
||||
width: 1000px;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
margin-top: calc((100vh - 470px) / 3);
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #ffffff;
|
||||
background-color: #f3f3f3;
|
||||
height: calc(100vh - (100vh - 470px) / 3);
|
||||
}
|
||||
|
||||
|
@ -120,12 +137,12 @@
|
|||
}
|
||||
|
||||
.login-page-language {
|
||||
font-size: 12px!important;
|
||||
font-size: 12px !important;
|
||||
margin-right: -32px !important;
|
||||
padding-top: 12px !important;
|
||||
padding-left: 0 !important;
|
||||
padding-bottom: 8px !important;
|
||||
color:#8F959E !important;
|
||||
color: #8F959E !important;
|
||||
font-weight: 350 !important;
|
||||
min-height: auto !important;
|
||||
}
|
||||
|
@ -137,14 +154,16 @@
|
|||
|
||||
.jms-title {
|
||||
font-size: 21px;
|
||||
font-weight:400;
|
||||
font-weight: 400;
|
||||
color: #151515;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.more-methods-title {
|
||||
position: relative;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.more-methods-title:before, .more-methods-title:after {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
|
@ -153,18 +172,23 @@
|
|||
border: 1px dashed #e7eaec;
|
||||
width: 35%;
|
||||
}
|
||||
|
||||
.more-methods-title:before {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.more-methods-title:after {
|
||||
right: 0;
|
||||
}
|
||||
.more-methods-title.ja:before, .more-methods-title.ja:after{
|
||||
|
||||
.more-methods-title.ja:before, .more-methods-title.ja:after {
|
||||
width: 26%;
|
||||
}
|
||||
|
||||
.captcha-field .form-group {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.auto-login.form-group .checkbox {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
@ -176,16 +200,20 @@
|
|||
.has-error .more-login {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.welcome-message {
|
||||
color: #646A73;
|
||||
}
|
||||
|
||||
.navbar-right .dropdown-menu {
|
||||
right: -24px!important;
|
||||
right: -24px !important;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
.auto_login_box {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.auto-login input[type=checkbox] {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
|
@ -201,9 +229,11 @@
|
|||
outline: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.auto-login input[type=checkbox]:checked {
|
||||
border: 4px solid var(--primary-color);
|
||||
}
|
||||
|
||||
.auto-login > .row::after {
|
||||
clear: none;
|
||||
}
|
||||
|
@ -218,11 +248,31 @@
|
|||
</a>
|
||||
</div>
|
||||
<div class="left-form-box {% if not form.challenge and not form.captcha %} no-captcha-challenge {% endif %}">
|
||||
<div style="background-color: white">
|
||||
<div class="jms-title">
|
||||
<img src="{{ INTERFACE.logo_text_green }}" class="jms-title-img" />
|
||||
<div style="position: relative;top: 50%;transform: translateY(-50%);">
|
||||
<div style='padding: 15px 60px; text-align: left'>
|
||||
<h2 style='font-weight: 400;display: inline'>
|
||||
{% trans 'Login' %}
|
||||
</h2>
|
||||
<ul class=" nav navbar-top-links navbar-right">
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle login-page-language" data-toggle="dropdown" href="#"
|
||||
target="_blank">
|
||||
<i class="fa fa-globe fa-lg" style="margin-right: 2px"></i>
|
||||
<span>{{ current_lang.title }}<b class="caret"></b></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu profile-dropdown dropdown-menu-right">
|
||||
{% for lang in langs %}
|
||||
<li>
|
||||
<a href="{% url 'i18n-switch' lang=lang.code %}">
|
||||
<span>{{ lang.title }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="contact-form col-md-10 col-md-offset-1">
|
||||
<div class="contact-form col-md-10 col-md-offset-1" style='float: none; overflow: hidden'>
|
||||
<form id="login-form" action="" method="post" role="form" novalidate="novalidate">
|
||||
{% csrf_token %}
|
||||
<div style="line-height: 17px;margin-bottom: 20px;color: #999999;">
|
||||
|
@ -230,37 +280,17 @@
|
|||
<p class="help-block red-fonts">
|
||||
{{ form.non_field_errors.as_text }}
|
||||
</p>
|
||||
{% else %}
|
||||
<p class="welcome-message">
|
||||
{% trans 'Welcome back, please enter username and password to login' %}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<ul class="nav navbar-top-links navbar-right">
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle login-page-language" data-toggle="dropdown" href="#" target="_blank">
|
||||
<i class="fa fa-globe fa-lg" style="margin-right: 2px"></i>
|
||||
<span>{{ current_lang.title }}<b class="caret"></b></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu profile-dropdown dropdown-menu-right">
|
||||
{% for lang in langs %}
|
||||
<li>
|
||||
<a href="{% url 'i18n-switch' lang=lang.code %}">
|
||||
<span>{{ lang.title }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{% bootstrap_field form.username show_label=False %}
|
||||
<div class="form-group {% if form.password.errors %} has-error {% endif %}">
|
||||
<input type="password" class="form-control" id="password" placeholder="{% trans 'Password' %}" required>
|
||||
<input id="password-hidden" type="text" style="display:none" name="{{ form.password.html_name }}">
|
||||
<input type="password" class="form-control" id="password" placeholder="{% trans 'Password' %}"
|
||||
required>
|
||||
<input id="password-hidden" type="text" style="display:none"
|
||||
name="{{ form.password.html_name }}">
|
||||
{% if form.password.errors %}
|
||||
<p class="help-block" style="text-align: left">
|
||||
<p class="help-block" style="text-align: left">
|
||||
{{ form.password.errors.as_text }}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
@ -306,7 +336,8 @@
|
|||
<div class="more-login-items">
|
||||
{% for method in auth_methods %}
|
||||
<a href="{{ method.url }}" class="more-login-item">
|
||||
<i class="fa"><img src="{{ method.logo }}" height="15" width="15"></i> {{ method.name }}
|
||||
<i class="fa">
|
||||
<img src="{{ method.logo }}" height="15" width="15"></i> {{ method.name }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
@ -320,6 +351,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
{% include '_foot_js.html' %}
|
||||
<script type="text/javascript" src="/static/js/plugins/jsencrypt/jsencrypt.min.js"></script>
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from django.templatetags.static import static
|
||||
from django.conf import settings
|
||||
from django.templatetags.static import static
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
default_interface = dict((
|
||||
('logo_logout', static('img/logo.png')),
|
||||
('logo_index', static('img/logo_text_white.png')),
|
||||
('logo_text_green', static('img/logo_text_green.png')),
|
||||
('login_image', static('img/login_image.jpg')),
|
||||
('login_image', static('img/login_image.png')),
|
||||
('favicon', static('img/facio.ico')),
|
||||
('login_title', _('JumpServer Open Source Bastion Host')),
|
||||
('theme', 'classic_green'),
|
||||
|
@ -37,6 +36,3 @@ def jumpserver_processor(request):
|
|||
'SECURITY_VIEW_AUTH_NEED_MFA': settings.SECURITY_VIEW_AUTH_NEED_MFA,
|
||||
})
|
||||
return context
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b02c5d36ea6ea96590be9a25dc6d3f1340a5af2aa940764243f85da1c756c732
|
||||
size 104221
|
||||
oid sha256:aec4662e56ce44daac5eea9fe6d39c21ce9b2c55cfb60006ad6f0e639329c552
|
||||
size 105895
|
||||
|
|
|
@ -340,9 +340,8 @@ msgid "App assets"
|
|||
msgstr "资产管理"
|
||||
|
||||
#: assets/automations/base/manager.py:123
|
||||
#, fuzzy
|
||||
msgid "{} disabled"
|
||||
msgstr "禁用"
|
||||
msgstr "{} 已禁用"
|
||||
|
||||
#: assets/const/account.py:6 audits/const.py:6 audits/const.py:64
|
||||
#: common/utils/ip/geoip/utils.py:31 common/utils/ip/geoip/utils.py:37
|
||||
|
@ -374,52 +373,45 @@ msgid "Password"
|
|||
msgstr "密码"
|
||||
|
||||
#: assets/const/account.py:13
|
||||
#, fuzzy
|
||||
#| msgid "SSH Key"
|
||||
msgid "SSH key"
|
||||
msgstr "SSH 密钥"
|
||||
|
||||
#: assets/const/account.py:14 authentication/models/access_key.py:33
|
||||
msgid "Access key"
|
||||
msgstr "Access key"
|
||||
msgstr "访问密钥"
|
||||
|
||||
#: assets/const/account.py:15 assets/models/_user.py:38
|
||||
#: authentication/models/sso_token.py:14
|
||||
msgid "Token"
|
||||
msgstr "Token"
|
||||
msgstr "令牌"
|
||||
|
||||
#: assets/const/automation.py:13
|
||||
msgid "Ping"
|
||||
msgstr ""
|
||||
|
||||
#: assets/const/automation.py:14
|
||||
#, fuzzy
|
||||
msgid "Gather facts"
|
||||
msgstr "收集账号"
|
||||
msgstr "收集资产信息"
|
||||
|
||||
#: assets/const/automation.py:15
|
||||
#, fuzzy
|
||||
msgid "Create account"
|
||||
msgstr "收集账号"
|
||||
msgstr "创建账号"
|
||||
|
||||
#: assets/const/automation.py:16
|
||||
#, fuzzy
|
||||
msgid "Change secret"
|
||||
msgstr "执行改密"
|
||||
msgstr "更改密码"
|
||||
|
||||
#: assets/const/automation.py:17
|
||||
#, fuzzy
|
||||
msgid "Verify account"
|
||||
msgstr "验证密码/密钥"
|
||||
msgstr "验证账号"
|
||||
|
||||
#: assets/const/automation.py:18
|
||||
#, fuzzy
|
||||
msgid "Gather accounts"
|
||||
msgstr "收集账号"
|
||||
|
||||
#: assets/const/automation.py:38 assets/serializers/account/base.py:26
|
||||
msgid "Specific"
|
||||
msgstr ""
|
||||
msgstr "特有的"
|
||||
|
||||
#: assets/const/automation.py:39 ops/const.py:20
|
||||
msgid "All assets use the same random password"
|
||||
|
@ -450,7 +442,7 @@ msgstr "主机"
|
|||
|
||||
#: assets/const/category.py:12
|
||||
msgid "Device"
|
||||
msgstr ""
|
||||
msgstr "网络设备"
|
||||
|
||||
#: assets/const/category.py:13 assets/models/asset/database.py:8
|
||||
#: assets/models/asset/database.py:34
|
||||
|
@ -458,14 +450,13 @@ msgid "Database"
|
|||
msgstr "数据库"
|
||||
|
||||
#: assets/const/category.py:14
|
||||
#, fuzzy
|
||||
msgid "Cloud service"
|
||||
msgstr "云管中心"
|
||||
msgstr "云服务"
|
||||
|
||||
#: assets/const/category.py:15 audits/const.py:62
|
||||
#: terminal/models/applet/applet.py:20
|
||||
msgid "Web"
|
||||
msgstr ""
|
||||
msgstr "Web"
|
||||
|
||||
#: assets/const/device.py:7 terminal/models/applet/applet.py:19
|
||||
#: tickets/const.py:8
|
||||
|
@ -473,28 +464,24 @@ msgid "General"
|
|||
msgstr "一般"
|
||||
|
||||
#: assets/const/device.py:8
|
||||
#, fuzzy
|
||||
msgid "Switch"
|
||||
msgstr "切换自"
|
||||
msgstr "交换机"
|
||||
|
||||
#: assets/const/device.py:9
|
||||
msgid "Router"
|
||||
msgstr ""
|
||||
msgstr "路由器"
|
||||
|
||||
#: assets/const/device.py:10
|
||||
msgid "Firewall"
|
||||
msgstr ""
|
||||
msgstr "防火墙"
|
||||
|
||||
#: assets/const/types.py:181
|
||||
#, fuzzy
|
||||
#| msgid "MFA type"
|
||||
msgid "All types"
|
||||
msgstr "MFA 类型"
|
||||
msgstr "所有类型"
|
||||
|
||||
#: assets/const/web.py:7
|
||||
#, fuzzy
|
||||
msgid "Website"
|
||||
msgstr "网站图标"
|
||||
msgstr "网站"
|
||||
|
||||
#: assets/models/_user.py:24
|
||||
msgid "Automatic managed"
|
||||
|
@ -656,9 +643,8 @@ msgid "Can view asset account template secret"
|
|||
msgstr "可以查看资产账号密码"
|
||||
|
||||
#: assets/models/account.py:108
|
||||
#, fuzzy
|
||||
msgid "Can change asset account template secret"
|
||||
msgstr "可以更改资产账号密码"
|
||||
msgstr "可以更改账号模版密码"
|
||||
|
||||
#: assets/models/asset/common.py:103 assets/models/platform.py:109
|
||||
#: assets/serializers/asset/common.py:65
|
||||
|
@ -702,9 +688,8 @@ msgid "Can test asset connectivity"
|
|||
msgstr "可以测试资产连接性"
|
||||
|
||||
#: assets/models/asset/common.py:226
|
||||
#, fuzzy
|
||||
msgid "Can push account to asset"
|
||||
msgstr "可以推送系统用户到资产"
|
||||
msgstr "可以推送账号到资产"
|
||||
|
||||
#: assets/models/asset/common.py:227
|
||||
msgid "Can match asset"
|
||||
|
@ -956,7 +941,7 @@ msgstr "校验日期"
|
|||
|
||||
#: assets/models/base.py:70
|
||||
msgid "Privileged"
|
||||
msgstr ""
|
||||
msgstr "特权账号"
|
||||
|
||||
#: assets/models/cmd_filter.py:28 perms/models/asset_permission.py:60
|
||||
#: users/models/group.py:25 users/models/user.py:681
|
||||
|
@ -996,9 +981,9 @@ msgid "No account"
|
|||
msgstr "没有账号"
|
||||
|
||||
#: assets/models/gateway.py:84
|
||||
#, fuzzy, python-brace-format
|
||||
#, python-brace-format
|
||||
msgid "Unable to connect to port {port} on {address}"
|
||||
msgstr "无法连接到 {ip} 上的端口 {port}"
|
||||
msgstr "无法连接到 {port} 上的端口 {address}"
|
||||
|
||||
#: assets/models/gateway.py:87 authentication/middleware.py:76
|
||||
#: xpack/plugins/cloud/providers/fc.py:48
|
||||
|
@ -1231,10 +1216,8 @@ msgid "Account template not found"
|
|||
msgstr "账号模版未找到"
|
||||
|
||||
#: assets/serializers/account/account.py:72
|
||||
#, fuzzy
|
||||
#| msgid "Asset Info"
|
||||
msgid "Asset not found"
|
||||
msgstr "资产信息"
|
||||
msgstr "资产不存在"
|
||||
|
||||
#: assets/serializers/account/backup.py:29
|
||||
#: assets/serializers/automations/base.py:34 ops/mixin.py:22 ops/mixin.py:102
|
||||
|
@ -2119,7 +2102,7 @@ msgstr "超级连接令牌"
|
|||
|
||||
#: authentication/models/private_token.py:9
|
||||
msgid "Private Token"
|
||||
msgstr "SSH密钥"
|
||||
msgstr "私有令牌"
|
||||
|
||||
#: authentication/models/sso_token.py:15
|
||||
msgid "Expired"
|
||||
|
@ -2142,8 +2125,6 @@ msgid "binding reminder"
|
|||
msgstr "绑定提醒"
|
||||
|
||||
#: authentication/serializers/connect_token_secret.py:105
|
||||
#, fuzzy
|
||||
#| msgid "Builtin"
|
||||
msgid "Is builtin"
|
||||
msgstr "内置的"
|
||||
|
||||
|
@ -2626,18 +2607,18 @@ msgid "This field is required."
|
|||
msgstr "该字段是必填项。"
|
||||
|
||||
#: common/drf/fields.py:78
|
||||
#, fuzzy, python-brace-format
|
||||
#, python-brace-format
|
||||
msgid "Invalid pk \"{pk_value}\" - object does not exist."
|
||||
msgstr "%s对象不存在"
|
||||
msgstr "错误的 id \"{pk_value}\" - 对象不存在"
|
||||
|
||||
#: common/drf/fields.py:79
|
||||
#, python-brace-format
|
||||
msgid "Incorrect type. Expected pk value, received {data_type}."
|
||||
msgstr ""
|
||||
msgstr "错误类型。期望 pk 值,收到 {data_type}。"
|
||||
|
||||
#: common/drf/fields.py:141
|
||||
msgid "Invalid data type, should be list"
|
||||
msgstr ""
|
||||
msgstr "错误的数据类型,应该是列表"
|
||||
|
||||
#: common/drf/fields.py:156
|
||||
msgid "Invalid choice: {}"
|
||||
|
@ -2653,7 +2634,7 @@ msgstr "解析文件错误: {}"
|
|||
|
||||
#: common/drf/serializers/common.py:86
|
||||
msgid "Children"
|
||||
msgstr ""
|
||||
msgstr "节点"
|
||||
|
||||
#: common/drf/serializers/common.py:94
|
||||
msgid "File"
|
||||
|
@ -3686,7 +3667,7 @@ msgstr "企业微信 认证"
|
|||
|
||||
#: settings/serializers/auth/base.py:18
|
||||
msgid "SSO Auth"
|
||||
msgstr "SSO Token 认证"
|
||||
msgstr "SSO 令牌认证"
|
||||
|
||||
#: settings/serializers/auth/base.py:19
|
||||
msgid "SAML2 Auth"
|
||||
|
@ -3882,8 +3863,6 @@ msgid "Enable PKCE"
|
|||
msgstr "启用 PKCE"
|
||||
|
||||
#: settings/serializers/auth/oidc.py:43
|
||||
#, fuzzy
|
||||
#| msgid "Connect method"
|
||||
msgid "Code challenge method"
|
||||
msgstr "连接方式"
|
||||
|
||||
|
@ -4047,7 +4026,7 @@ msgstr "模板+签名不能超过65个字"
|
|||
|
||||
#: settings/serializers/auth/sso.py:13
|
||||
msgid "Enable SSO auth"
|
||||
msgstr "启用 SSO Token 认证"
|
||||
msgstr "启用 SSO 令牌认证"
|
||||
|
||||
#: settings/serializers/auth/sso.py:14
|
||||
msgid "Other service can using SSO token login to JumpServer without password"
|
||||
|
@ -4055,7 +4034,7 @@ msgstr "其它系统可以使用 SSO Token 对接 JumpServer, 免去登录的过
|
|||
|
||||
#: settings/serializers/auth/sso.py:17
|
||||
msgid "SSO auth key TTL"
|
||||
msgstr "Token 有效期"
|
||||
msgstr "令牌有效期"
|
||||
|
||||
#: settings/serializers/auth/sso.py:17
|
||||
#: xpack/plugins/cloud/serializers/account_attrs.py:176
|
||||
|
@ -5662,8 +5641,6 @@ msgid "Run command"
|
|||
msgstr "运行的命令"
|
||||
|
||||
#: tickets/models/ticket/command_confirm.py:19
|
||||
#, fuzzy
|
||||
#| msgid "Command filter"
|
||||
msgid "Command filter acl"
|
||||
msgstr "命令过滤器"
|
||||
|
||||
|
@ -5712,9 +5689,8 @@ msgid "Login asset"
|
|||
msgstr "登录资产"
|
||||
|
||||
#: tickets/models/ticket/login_asset_confirm.py:17
|
||||
#, fuzzy
|
||||
msgid "Login account"
|
||||
msgstr "登录访问控制"
|
||||
msgstr "登录账号"
|
||||
|
||||
#: tickets/models/ticket/login_confirm.py:12
|
||||
msgid "Login datetime"
|
||||
|
@ -6342,7 +6318,7 @@ msgstr "非本地用户仅允许从第三方平台登录,不支持修改密码
|
|||
|
||||
#: users/views/profile/reset.py:149 users/views/profile/reset.py:160
|
||||
msgid "Token invalid or expired"
|
||||
msgstr "Token错误或失效"
|
||||
msgstr "令牌错误或失效"
|
||||
|
||||
#: users/views/profile/reset.py:165
|
||||
msgid "User auth from {}, go there change password"
|
||||
|
|
|
@ -13,7 +13,8 @@ class AdHocRunner:
|
|||
"reboot", 'shutdown', 'poweroff', 'halt', 'dd', 'half', 'top'
|
||||
]
|
||||
|
||||
def __init__(self, inventory, module, module_args='', pattern='*', project_dir='/tmp/', extra_vars={}):
|
||||
def __init__(self, inventory, module, module_args='', pattern='*', project_dir='/tmp/', extra_vars={},
|
||||
dry_run=False):
|
||||
self.id = uuid.uuid4()
|
||||
self.inventory = inventory
|
||||
self.pattern = pattern
|
||||
|
@ -23,6 +24,7 @@ class AdHocRunner:
|
|||
self.cb = DefaultCallback()
|
||||
self.runner = None
|
||||
self.extra_vars = extra_vars
|
||||
self.dry_run = dry_run
|
||||
|
||||
def check_module(self):
|
||||
if self.module not in self.cmd_modules_choices:
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from django.db.models import Count
|
||||
from rest_framework.views import APIView
|
||||
from django.shortcuts import get_object_or_404
|
||||
from rest_framework.response import Response
|
||||
|
@ -5,12 +6,14 @@ from rest_framework.response import Response
|
|||
from ops.models import Job, JobExecution
|
||||
from ops.serializers.job import JobSerializer, JobExecutionSerializer
|
||||
|
||||
__all__ = ['JobViewSet', 'JobExecutionViewSet', 'JobRunVariableHelpAPIView', 'JobAssetDetail', 'JobExecutionTaskDetail']
|
||||
__all__ = ['JobViewSet', 'JobExecutionViewSet', 'JobRunVariableHelpAPIView',
|
||||
'JobAssetDetail', 'JobExecutionTaskDetail','FrequentUsernames']
|
||||
|
||||
from ops.tasks import run_ops_job_execution
|
||||
from ops.variables import JMS_JOB_VARIABLE_HELP
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
from orgs.utils import tmp_to_org, get_current_org_id, get_current_org
|
||||
from assets.models import Account
|
||||
|
||||
|
||||
def set_task_to_serializer_data(serializer, task):
|
||||
|
@ -111,3 +114,12 @@ class JobExecutionTaskDetail(APIView):
|
|||
'is_success': execution.is_success,
|
||||
'time_cost': execution.time_cost,
|
||||
})
|
||||
|
||||
|
||||
class FrequentUsernames(APIView):
|
||||
rbac_perms = ()
|
||||
permission_classes = ()
|
||||
|
||||
def get(self, request, **kwargs):
|
||||
top_accounts = Account.objects.all().values('username').annotate(total=Count('username')).order_by('total')
|
||||
return Response(data=top_accounts)
|
||||
|
|
|
@ -166,6 +166,10 @@ class JobExecution(JMSOrgBaseModel):
|
|||
return
|
||||
result = self.current_job.args
|
||||
result += " chdir={}".format(self.current_job.chdir)
|
||||
|
||||
if self.current_job.module in ['python']:
|
||||
result += " executable={}".format(self.current_job.module)
|
||||
print(result)
|
||||
return self.job.args
|
||||
|
||||
def get_runner(self):
|
||||
|
@ -187,9 +191,17 @@ class JobExecution(JMSOrgBaseModel):
|
|||
|
||||
if self.current_job.type == 'adhoc':
|
||||
args = self.compile_shell()
|
||||
module = "shell"
|
||||
if self.current_job.module not in ['python']:
|
||||
module = self.current_job.module
|
||||
|
||||
runner = AdHocRunner(
|
||||
self.inventory_path, self.current_job.module, module_args=args,
|
||||
pattern="all", project_dir=self.private_dir, extra_vars=extra_vars,
|
||||
self.inventory_path,
|
||||
module,
|
||||
module_args=args,
|
||||
pattern="all",
|
||||
project_dir=self.private_dir,
|
||||
extra_vars=extra_vars,
|
||||
)
|
||||
elif self.current_job.type == 'playbook':
|
||||
runner = PlaybookRunner(
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from django.utils.translation import ugettext as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from assets.models import Node
|
||||
from common.drf.fields import ReadableHiddenField
|
||||
from ops.mixin import PeriodTaskSerializerMixin
|
||||
from ops.models import Job, JobExecution
|
||||
|
@ -10,6 +12,16 @@ from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
|||
class JobSerializer(BulkOrgResourceModelSerializer, PeriodTaskSerializerMixin):
|
||||
creator = ReadableHiddenField(default=serializers.CurrentUserDefault())
|
||||
run_after_save = serializers.BooleanField(label=_("Run after save"), default=False, required=False)
|
||||
nodes = serializers.ListField(required=False, child=serializers.CharField())
|
||||
|
||||
def create(self, validated_data):
|
||||
assets = validated_data.__getitem__('assets')
|
||||
node_ids = validated_data.pop('nodes')
|
||||
if node_ids:
|
||||
nodes = Node.objects.filter(id__in=node_ids)
|
||||
assets.extend(
|
||||
Node.get_nodes_all_assets(*nodes).exclude(id__in=[asset.id for asset in assets]))
|
||||
return super().create(validated_data)
|
||||
|
||||
class Meta:
|
||||
model = Job
|
||||
|
@ -22,7 +34,7 @@ class JobSerializer(BulkOrgResourceModelSerializer, PeriodTaskSerializerMixin):
|
|||
"chdir",
|
||||
"comment",
|
||||
"summary",
|
||||
"is_periodic", "interval", "crontab", "run_after_save"
|
||||
"is_periodic", "interval", "crontab", "run_after_save", "nodes"
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ urlpatterns = [
|
|||
path('variables/help/', api.JobRunVariableHelpAPIView.as_view(), name='variable-help'),
|
||||
path('job-execution/asset-detail/', api.JobAssetDetail.as_view(), name='asset-detail'),
|
||||
path('job-execution/task-detail/', api.JobExecutionTaskDetail.as_view(), name='task-detail'),
|
||||
path('frequent-username/', api.FrequentUsernames.as_view(), name='frequent-usernames'),
|
||||
path('ansible/job-execution/<uuid:pk>/log/', api.AnsibleTaskLogApi.as_view(), name='job-execution-log'),
|
||||
|
||||
path('celery/task/<uuid:name>/task-execution/<uuid:pk>/log/', api.CeleryTaskExecutionLogApi.as_view(),
|
||||
|
|
|
@ -25,23 +25,25 @@ user_permission_urlpatterns = [
|
|||
name='user-direct-assets-as-tree'),
|
||||
path('<str:user>/ungroup/assets/tree/', api.UserUngroupAssetsAsTreeApi.as_view(),
|
||||
name='user-ungroup-assets-as-tree'),
|
||||
# tree-node
|
||||
|
||||
# tree-node,不包含资产
|
||||
path('<str:user>/nodes/tree/', api.UserAllPermedNodesAsTreeApi.as_view(),
|
||||
name='user-all-nodes-as-tree'),
|
||||
path('<str:user>/nodes/children/tree/', api.UserPermedNodeChildrenAsTreeApi.as_view(),
|
||||
name='user-node-children-as-tree'),
|
||||
|
||||
# tree-node-with-asset
|
||||
# 异步树
|
||||
path('<str:user>/nodes/children-with-assets/tree/',
|
||||
api.UserPermedNodeChildrenWithAssetsAsTreeApi.as_view(),
|
||||
name='user-node-children-with-assets-as-tree'),
|
||||
# 同步树
|
||||
path('<str:user>/nodes/all-with-assets/tree/',
|
||||
api.UserPermedNodesWithAssetsAsTreeApi.as_view(),
|
||||
name='user-nodes-with-assets-as-tree'),
|
||||
path('<str:user>/nodes/children-with-k8s/tree/',
|
||||
api.UserGrantedK8sAsTreeApi.as_view(),
|
||||
name='user-nodes-children-with-k8s-as-tree'),
|
||||
|
||||
# 同步树
|
||||
path('<str:user>/nodes-with-assets/tree/', api.UserPermedNodesWithAssetsAsTreeApi.as_view(),
|
||||
name='user-nodes-with-assets-as-tree'),
|
||||
# accounts
|
||||
path('<str:user>/assets/<uuid:asset_id>/accounts/', api.UserPermedAssetAccountsApi.as_view(),
|
||||
name='user-permed-asset-accounts'),
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 225 KiB |
Binary file not shown.
After Width: | Height: | Size: 184 KiB |
Binary file not shown.
Before Width: | Height: | Size: 65 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 5.6 KiB |
|
@ -26,8 +26,14 @@ logger = get_logger(__file__)
|
|||
|
||||
|
||||
class RolesSerializerMixin(serializers.Serializer):
|
||||
system_roles = ObjectRelatedField(queryset=Role.system_roles, label=_("System roles"), many=True)
|
||||
org_roles = ObjectRelatedField(queryset=Role.org_roles, label=_("Org roles"), many=True)
|
||||
system_roles = ObjectRelatedField(
|
||||
queryset=Role.system_roles, attrs=('id', 'display_name'),
|
||||
label=_("System roles"), many=True
|
||||
)
|
||||
org_roles = ObjectRelatedField(
|
||||
queryset=Role.org_roles, attrs=('id', 'display_name'),
|
||||
label=_("Org roles"), many=True
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_system_roles_display(user):
|
||||
|
|
Loading…
Reference in New Issue