Merge pull request #4338 from jumpserver/dev

merge(master): Merge from dev to master
pull/4357/head
BaiJiangJie 2020-07-16 10:50:26 +08:00 committed by GitHub
commit 08fdc57543
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 194 additions and 122 deletions

View File

@ -0,0 +1,18 @@
# Generated by Django 2.2.10 on 2020-07-11 09:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('assets', '0049_systemuser_sftp_root'),
]
operations = [
migrations.AlterField(
model_name='asset',
name='created_by',
field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'),
),
]

View File

@ -1,4 +1,4 @@
# Generated by Django 2.2.10 on 2020-07-02 08:02 # Generated by Django 2.2.10 on 2020-07-13 03:43
from django.db import migrations, models from django.db import migrations, models
@ -6,7 +6,7 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('assets', '0049_systemuser_sftp_root'), ('assets', '0050_auto_20200711_1740'),
] ]
operations = [ operations = [

View File

@ -0,0 +1,22 @@
# Generated by Django 2.2.10 on 2020-07-15 07:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('assets', '0051_auto_20200713_1143'),
]
operations = [
migrations.AlterField(
model_name='commandfilter',
name='name',
field=models.CharField(max_length=64, verbose_name='Name'),
),
migrations.AlterUniqueTogether(
name='commandfilter',
unique_together={('org_id', 'name')},
),
]

View File

@ -221,7 +221,7 @@ class Asset(ProtocolsMixin, NodesRelationMixin, OrgModelMixin):
hostname_raw = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Hostname raw')) hostname_raw = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Hostname raw'))
labels = models.ManyToManyField('assets.Label', blank=True, related_name='assets', verbose_name=_("Labels")) labels = models.ManyToManyField('assets.Label', blank=True, related_name='assets', verbose_name=_("Labels"))
created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by')) created_by = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Created by'))
date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True, verbose_name=_('Date created')) date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True, verbose_name=_('Date created'))
comment = models.TextField(max_length=128, default='', blank=True, verbose_name=_('Comment')) comment = models.TextField(max_length=128, default='', blank=True, verbose_name=_('Comment'))

View File

@ -3,7 +3,6 @@
from django.db import models, transaction from django.db import models, transaction
from django.db.models import Max from django.db.models import Max
from django.core.cache import cache
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from orgs.mixins.models import OrgManager from orgs.mixins.models import OrgManager
@ -59,12 +58,10 @@ class AuthBook(BaseUser):
""" """
username = kwargs['username'] username = kwargs['username']
asset = kwargs['asset'] asset = kwargs['asset']
key_lock = 'KEY_LOCK_CREATE_AUTH_BOOK_{}_{}'.format(username, asset.id)
with cache.lock(key_lock):
with transaction.atomic(): with transaction.atomic():
cls.objects.filter( # 使用select_for_update限制并发创建相同的username、asset条目
username=username, asset=asset, is_latest=True instances = cls.objects.select_for_update().filter(username=username, asset=asset)
).update(is_latest=False) instances.filter(is_latest=True).update(is_latest=False)
max_version = cls.get_max_version(username, asset) max_version = cls.get_max_version(username, asset)
kwargs.update({ kwargs.update({
'version': max_version + 1, 'version': max_version + 1,

View File

@ -18,7 +18,7 @@ __all__ = [
class CommandFilter(OrgModelMixin): class CommandFilter(OrgModelMixin):
id = models.UUIDField(default=uuid.uuid4, primary_key=True) id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=64, unique=True, verbose_name=_("Name")) name = models.CharField(max_length=64, verbose_name=_("Name"))
is_active = models.BooleanField(default=True, verbose_name=_('Is active')) is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
comment = models.TextField(blank=True, default='', verbose_name=_("Comment")) comment = models.TextField(blank=True, default='', verbose_name=_("Comment"))
date_created = models.DateTimeField(auto_now_add=True) date_created = models.DateTimeField(auto_now_add=True)
@ -29,6 +29,7 @@ class CommandFilter(OrgModelMixin):
return self.name return self.name
class Meta: class Meta:
unique_together = [('org_id', 'name')]
verbose_name = _("Command filter") verbose_name = _("Command filter")

View File

@ -185,7 +185,9 @@ def on_asset_nodes_add(sender, instance=None, action='', model=None, pk_set=None
system_users_assets = defaultdict(set) system_users_assets = defaultdict(set)
for system_user in system_users: for system_user in system_users:
system_users_assets[system_user].update(set(assets)) assets_has_set = system_user.assets.all().filter(id__in=assets).values_list('id', flat=True)
assets_remain = set(assets) - set(assets_has_set)
system_users_assets[system_user].update(assets_remain)
for system_user, _assets in system_users_assets.items(): for system_user, _assets in system_users_assets.items():
system_user.assets.add(*tuple(_assets)) system_user.assets.add(*tuple(_assets))

View File

@ -64,7 +64,7 @@ GATHER_ASSET_USERS_TASKS = [
"action": { "action": {
"module": "shell", "module": "shell",
"args": "users=$(getent passwd | grep -v 'nologin' | " "args": "users=$(getent passwd | grep -v 'nologin' | "
"grep -v 'shudown' | awk -F: '{ print $1 }');for i in $users;do last -F $i -1 | " "grep -v 'shudown' | awk -F: '{ print $1 }');for i in $users;do last -w -F $i -1 | "
"head -1 | grep -v '^$' | awk '{ print $1\"@\"$3\"@\"$5,$6,$7,$8 }';done" "head -1 | grep -v '^$' | awk '{ print $1\"@\"$3\"@\"$5,$6,$7,$8 }';done"
} }
} }

View File

@ -17,7 +17,7 @@ class FTPLogSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = models.FTPLog model = models.FTPLog
fields = ( fields = (
'id', 'user', 'remote_addr', 'asset', 'system_user', 'id', 'user', 'remote_addr', 'asset', 'system_user', 'org_id',
'operate', 'filename', 'is_success', 'date_start', 'operate_display' 'operate', 'filename', 'is_success', 'date_start', 'operate_display'
) )
@ -40,7 +40,7 @@ class OperateLogSerializer(serializers.ModelSerializer):
model = models.OperateLog model = models.OperateLog
fields = ( fields = (
'id', 'user', 'action', 'resource_type', 'resource', 'id', 'user', 'action', 'resource_type', 'resource',
'remote_addr', 'datetime' 'remote_addr', 'datetime', 'org_id'
) )
@ -66,7 +66,7 @@ class CommandExecutionSerializer(serializers.ModelSerializer):
fields_mini = ['id'] fields_mini = ['id']
fields_small = fields_mini + [ fields_small = fields_mini + [
'run_as', 'command', 'user', 'is_finished', 'run_as', 'command', 'user', 'is_finished',
'date_start', 'result', 'is_success' 'date_start', 'result', 'is_success', 'org_id'
] ]
fields = fields_small + ['hosts', 'run_as_display', 'user_display'] fields = fields_small + ['hosts', 'run_as_display', 'user_display']
extra_kwargs = { extra_kwargs = {

Binary file not shown.

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: JumpServer 0.3.3\n" "Project-Id-Version: JumpServer 0.3.3\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-07-09 10:05+0800\n" "POT-Creation-Date: 2020-07-15 17:13+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ibuler <ibuler@qq.com>\n" "Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: JumpServer team<ibuler@qq.com>\n" "Language-Team: JumpServer team<ibuler@qq.com>\n"
@ -85,7 +85,7 @@ msgstr "数据库"
#: users/templates/users/user_group_list.html:16 #: users/templates/users/user_group_list.html:16
#: users/templates/users/user_profile.html:138 #: users/templates/users/user_profile.html:138
#: xpack/plugins/change_auth_plan/models.py:77 xpack/plugins/cloud/models.py:53 #: xpack/plugins/change_auth_plan/models.py:77 xpack/plugins/cloud/models.py:53
#: xpack/plugins/cloud/models.py:139 xpack/plugins/gathered_user/models.py:26 #: xpack/plugins/cloud/models.py:140 xpack/plugins/gathered_user/models.py:26
msgid "Comment" msgid "Comment"
msgstr "备注" msgstr "备注"
@ -100,7 +100,7 @@ msgid "DatabaseApp"
msgstr "数据库应用" msgstr "数据库应用"
#: applications/models/remote_app.py:23 assets/models/asset.py:352 #: applications/models/remote_app.py:23 assets/models/asset.py:352
#: assets/models/authbook.py:27 assets/models/gathered_user.py:14 #: assets/models/authbook.py:26 assets/models/gathered_user.py:14
#: assets/serializers/admin_user.py:32 assets/serializers/asset_user.py:47 #: assets/serializers/admin_user.py:32 assets/serializers/asset_user.py:47
#: assets/serializers/asset_user.py:84 assets/serializers/system_user.py:44 #: assets/serializers/asset_user.py:84 assets/serializers/system_user.py:44
#: assets/serializers/system_user.py:176 audits/models.py:38 #: assets/serializers/system_user.py:176 audits/models.py:38
@ -111,7 +111,7 @@ msgstr "数据库应用"
#: users/templates/users/user_asset_permission.html:70 #: users/templates/users/user_asset_permission.html:70
#: users/templates/users/user_granted_remote_app.html:36 #: users/templates/users/user_granted_remote_app.html:36
#: xpack/plugins/change_auth_plan/models.py:283 #: xpack/plugins/change_auth_plan/models.py:283
#: xpack/plugins/cloud/models.py:269 #: xpack/plugins/cloud/models.py:266
msgid "Asset" msgid "Asset"
msgstr "资产" msgstr "资产"
@ -135,7 +135,7 @@ msgstr "参数"
#: perms/models/base.py:54 users/models/user.py:508 #: perms/models/base.py:54 users/models/user.py:508
#: users/serializers/group.py:35 users/templates/users/user_detail.html:97 #: users/serializers/group.py:35 users/templates/users/user_detail.html:97
#: xpack/plugins/change_auth_plan/models.py:81 xpack/plugins/cloud/models.py:56 #: xpack/plugins/change_auth_plan/models.py:81 xpack/plugins/cloud/models.py:56
#: xpack/plugins/cloud/models.py:145 xpack/plugins/gathered_user/models.py:30 #: xpack/plugins/cloud/models.py:146 xpack/plugins/gathered_user/models.py:30
msgid "Created by" msgid "Created by"
msgstr "创建者" msgstr "创建者"
@ -148,7 +148,7 @@ msgstr "创建者"
#: common/mixins/models.py:50 ops/models/adhoc.py:38 ops/models/command.py:27 #: common/mixins/models.py:50 ops/models/adhoc.py:38 ops/models/command.py:27
#: orgs/models.py:17 perms/models/base.py:55 users/models/group.py:18 #: orgs/models.py:17 perms/models/base.py:55 users/models/group.py:18
#: users/templates/users/user_group_detail.html:58 #: users/templates/users/user_group_detail.html:58
#: xpack/plugins/cloud/models.py:59 xpack/plugins/cloud/models.py:148 #: xpack/plugins/cloud/models.py:59 xpack/plugins/cloud/models.py:149
msgid "Date created" msgid "Date created"
msgstr "创建日期" msgstr "创建日期"
@ -247,7 +247,7 @@ msgstr "激活"
#: assets/models/asset.py:199 assets/models/cluster.py:19 #: assets/models/asset.py:199 assets/models/cluster.py:19
#: assets/models/user.py:65 templates/_nav.html:44 #: assets/models/user.py:65 templates/_nav.html:44
#: xpack/plugins/cloud/models.py:133 #: xpack/plugins/cloud/models.py:133 xpack/plugins/cloud/serializers.py:82
msgid "Admin user" msgid "Admin user"
msgstr "管理用户" msgstr "管理用户"
@ -319,19 +319,19 @@ msgstr "主机名原始"
msgid "Labels" msgid "Labels"
msgstr "标签管理" msgstr "标签管理"
#: assets/models/authbook.py:18 #: assets/models/authbook.py:17
msgid "Bulk delete deny" msgid "Bulk delete deny"
msgstr "拒绝批量删除" msgstr "拒绝批量删除"
#: assets/models/authbook.py:28 #: assets/models/authbook.py:27
msgid "Latest version" msgid "Latest version"
msgstr "最新版本" msgstr "最新版本"
#: assets/models/authbook.py:29 #: assets/models/authbook.py:28
msgid "Version" msgid "Version"
msgstr "版本" msgstr "版本"
#: assets/models/authbook.py:38 #: assets/models/authbook.py:37
msgid "AuthBook" msgid "AuthBook"
msgstr "" msgstr ""
@ -590,7 +590,7 @@ msgstr "键"
#: users/templates/users/user_asset_permission.html:41 #: users/templates/users/user_asset_permission.html:41
#: users/templates/users/user_asset_permission.html:73 #: users/templates/users/user_asset_permission.html:73
#: users/templates/users/user_asset_permission.html:158 #: users/templates/users/user_asset_permission.html:158
#: xpack/plugins/cloud/models.py:129 #: xpack/plugins/cloud/models.py:129 xpack/plugins/cloud/serializers.py:83
msgid "Node" msgid "Node"
msgstr "节点" msgstr "节点"
@ -612,7 +612,7 @@ msgid "Assets"
msgstr "资产管理" msgstr "资产管理"
#: assets/models/user.py:111 templates/_nav.html:17 #: assets/models/user.py:111 templates/_nav.html:17
#: users/views/profile/password.py:40 users/views/profile/pubkey.py:36 #: users/views/profile/password.py:42 users/views/profile/pubkey.py:36
msgid "Users" msgid "Users"
msgstr "用户管理" msgstr "用户管理"
@ -874,7 +874,7 @@ msgstr "没有匹配到资产,结束任务"
#: users/templates/users/user_list.html:98 #: users/templates/users/user_list.html:98
#: users/templates/users/user_remote_app_permission.html:111 #: users/templates/users/user_remote_app_permission.html:111
msgid "Delete" msgid "Delete"
msgstr "删除文件" msgstr "删除"
#: audits/models.py:27 #: audits/models.py:27
msgid "Upload" msgid "Upload"
@ -976,7 +976,7 @@ msgstr "启用"
msgid "-" msgid "-"
msgstr "" msgstr ""
#: audits/models.py:96 xpack/plugins/cloud/models.py:204 #: audits/models.py:96 xpack/plugins/cloud/models.py:201
msgid "Failed" msgid "Failed"
msgstr "失败" msgstr "失败"
@ -1006,13 +1006,13 @@ msgid "MFA"
msgstr "多因子认证" msgstr "多因子认证"
#: audits/models.py:105 xpack/plugins/change_auth_plan/models.py:304 #: audits/models.py:105 xpack/plugins/change_auth_plan/models.py:304
#: xpack/plugins/cloud/models.py:217 #: xpack/plugins/cloud/models.py:214
msgid "Reason" msgid "Reason"
msgstr "原因" msgstr "原因"
#: audits/models.py:106 tickets/serializers/request_asset_perm.py:53 #: audits/models.py:106 tickets/serializers/request_asset_perm.py:53
#: tickets/serializers/ticket.py:25 xpack/plugins/cloud/models.py:214 #: tickets/serializers/ticket.py:25 xpack/plugins/cloud/models.py:211
#: xpack/plugins/cloud/models.py:272 #: xpack/plugins/cloud/models.py:269
msgid "Status" msgid "Status"
msgstr "状态" msgstr "状态"
@ -1025,7 +1025,7 @@ msgid "Is success"
msgstr "是否成功" msgstr "是否成功"
#: audits/serializers.py:73 ops/models/command.py:24 #: audits/serializers.py:73 ops/models/command.py:24
#: xpack/plugins/cloud/models.py:212 #: xpack/plugins/cloud/models.py:209
msgid "Result" msgid "Result"
msgstr "结果" msgstr "结果"
@ -1144,8 +1144,8 @@ msgid ""
"after {} minutes)" "after {} minutes)"
msgstr "账号已被锁定(请联系管理员解锁 或 {}分钟后重试)" msgstr "账号已被锁定(请联系管理员解锁 或 {}分钟后重试)"
#: authentication/errors.py:50 users/views/profile/otp.py:63 #: authentication/errors.py:50 users/views/profile/otp.py:107
#: users/views/profile/otp.py:102 users/views/profile/otp.py:121 #: users/views/profile/otp.py:146 users/views/profile/otp.py:166
msgid "MFA code invalid, or ntp sync server time" msgid "MFA code invalid, or ntp sync server time"
msgstr "MFA验证码不正确或者服务器端时间不对" msgstr "MFA验证码不正确或者服务器端时间不对"
@ -1440,10 +1440,6 @@ msgstr "字段必须唯一"
msgid "<h1>Flow service unavailable, check it</h1>" msgid "<h1>Flow service unavailable, check it</h1>"
msgstr "" msgstr ""
#: jumpserver/views/index.py:26 templates/_nav.html:7
msgid "Dashboard"
msgstr "仪表盘"
#: jumpserver/views/other.py:26 #: jumpserver/views/other.py:26
msgid "" msgid ""
"<div>Luna is a separately deployed program, you need to deploy Luna, koko, " "<div>Luna is a separately deployed program, you need to deploy Luna, koko, "
@ -1626,6 +1622,14 @@ msgstr "更新任务内容: {}"
msgid "Disk used more than 80%: {} => {}" msgid "Disk used more than 80%: {} => {}"
msgstr "磁盘使用率超过 80%: {} => {}" msgstr "磁盘使用率超过 80%: {} => {}"
#: orgs/api.py:57
msgid "Organization contains undeleted resources"
msgstr "组织内包含未删除的资源"
#: orgs/api.py:61
msgid "The current organization cannot be deleted"
msgstr "当能删除当前所在组织"
#: orgs/mixins/models.py:56 orgs/mixins/serializers.py:26 orgs/models.py:31 #: orgs/mixins/models.py:56 orgs/mixins/serializers.py:26 orgs/models.py:31
msgid "Organization" msgid "Organization"
msgstr "组织" msgstr "组织"
@ -2019,6 +2023,10 @@ msgstr ""
"\"%(user_pubkey_update)s\"> 链接 </a> 更新\n" "\"%(user_pubkey_update)s\"> 链接 </a> 更新\n"
" " " "
#: templates/_nav.html:7
msgid "Dashboard"
msgstr "仪表盘"
#: templates/_nav.html:20 #: templates/_nav.html:20
msgid "User list" msgid "User list"
msgstr "用户列表" msgstr "用户列表"
@ -2421,6 +2429,10 @@ msgstr "线程数"
msgid "Boot Time" msgid "Boot Time"
msgstr "运行时间" msgstr "运行时间"
#: terminal/models.py:191
msgid "Login from"
msgstr "登录来源"
#: terminal/models.py:195 #: terminal/models.py:195
msgid "Replay" msgid "Replay"
msgstr "回放" msgstr "回放"
@ -2433,11 +2445,11 @@ msgstr "结束日期"
msgid "Args" msgid "Args"
msgstr "参数" msgstr "参数"
#: tickets/api/request_asset_perm.py:40 #: tickets/api/request_asset_perm.py:41
msgid "Ticket closed" msgid "Ticket closed"
msgstr "工单已关闭" msgstr "工单已关闭"
#: tickets/api/request_asset_perm.py:43 #: tickets/api/request_asset_perm.py:44
#, python-format #, python-format
msgid "Ticket has %s" msgid "Ticket has %s"
msgstr "工单已%s" msgstr "工单已%s"
@ -2446,27 +2458,27 @@ msgstr "工单已%s"
msgid "Superuser" msgid "Superuser"
msgstr "超级管理员" msgstr "超级管理员"
#: tickets/api/request_asset_perm.py:102 #: tickets/api/request_asset_perm.py:99
msgid "Confirm assets first" msgid "Confirm assets first"
msgstr "请先确认资产" msgstr "请先确认资产"
#: tickets/api/request_asset_perm.py:105 #: tickets/api/request_asset_perm.py:102
msgid "Confirmed assets changed" msgid "Confirmed assets changed"
msgstr "确认的资产变更了" msgstr "确认的资产变更了"
#: tickets/api/request_asset_perm.py:109 #: tickets/api/request_asset_perm.py:106
msgid "Confirm system-user first" msgid "Confirm system-user first"
msgstr "请先确认系统用户" msgstr "请先确认系统用户"
#: tickets/api/request_asset_perm.py:113 #: tickets/api/request_asset_perm.py:110
msgid "Confirmed system-user changed" msgid "Confirmed system-user changed"
msgstr "确认的系统用户变更了" msgstr "确认的系统用户变更了"
#: tickets/api/request_asset_perm.py:116 xpack/plugins/cloud/models.py:205 #: tickets/api/request_asset_perm.py:113 xpack/plugins/cloud/models.py:202
msgid "Succeed" msgid "Succeed"
msgstr "成功" msgstr "成功"
#: tickets/api/request_asset_perm.py:124 #: tickets/api/request_asset_perm.py:121
msgid "{} request assets, approved by {}" msgid "{} request assets, approved by {}"
msgstr "{} 申请资产,通过人 {}" msgstr "{} 申请资产,通过人 {}"
@ -2720,7 +2732,7 @@ msgstr "复制用户公钥到这里"
msgid "Join user groups" msgid "Join user groups"
msgstr "添加到用户组" msgstr "添加到用户组"
#: users/forms/user.py:103 users/views/profile/password.py:57 #: users/forms/user.py:103 users/views/profile/password.py:59
#: users/views/profile/reset.py:123 #: users/views/profile/reset.py:123
msgid "* Your password does not meet the requirements" msgid "* Your password does not meet the requirements"
msgstr "* 您的密码不符合要求" msgstr "* 您的密码不符合要求"
@ -2837,7 +2849,7 @@ msgstr "安全令牌验证"
#: users/templates/users/_base_otp.html:14 users/templates/users/_user.html:13 #: users/templates/users/_base_otp.html:14 users/templates/users/_user.html:13
#: users/templates/users/user_profile_update.html:55 #: users/templates/users/user_profile_update.html:55
#: xpack/plugins/cloud/models.py:119 #: xpack/plugins/cloud/models.py:119 xpack/plugins/cloud/serializers.py:81
msgid "Account" msgid "Account"
msgstr "账户" msgstr "账户"
@ -3552,27 +3564,27 @@ msgstr ""
" <br>\n" " <br>\n"
" " " "
#: users/views/profile/otp.py:145 #: users/views/profile/otp.py:190
msgid "MFA enable success" msgid "MFA enable success"
msgstr "多因子认证启用成功" msgstr "多因子认证启用成功"
#: users/views/profile/otp.py:146 #: users/views/profile/otp.py:191
msgid "MFA enable success, return login page" msgid "MFA enable success, return login page"
msgstr "多因子认证启用成功,返回到登录页面" msgstr "多因子认证启用成功,返回到登录页面"
#: users/views/profile/otp.py:148 #: users/views/profile/otp.py:193
msgid "MFA disable success" msgid "MFA disable success"
msgstr "多因子认证禁用成功" msgstr "多因子认证禁用成功"
#: users/views/profile/otp.py:149 #: users/views/profile/otp.py:194
msgid "MFA disable success, return login page" msgid "MFA disable success, return login page"
msgstr "多因子认证禁用成功,返回登录页面" msgstr "多因子认证禁用成功,返回登录页面"
#: users/views/profile/password.py:41 #: users/views/profile/password.py:43
msgid "Password update" msgid "Password update"
msgstr "密码更新" msgstr "密码更新"
#: users/views/profile/password.py:72 #: users/views/profile/password.py:74
msgid "Password invalid" msgid "Password invalid"
msgstr "用户名或密码无效" msgstr "用户名或密码无效"
@ -3732,55 +3744,55 @@ msgstr "地域"
msgid "Instances" msgid "Instances"
msgstr "实例" msgstr "实例"
#: xpack/plugins/cloud/models.py:136 xpack/plugins/cloud/serializers.py:80 #: xpack/plugins/cloud/models.py:137 xpack/plugins/cloud/serializers.py:85
msgid "Covered always" msgid "Always update"
msgstr "总是被覆盖" msgstr "总是更新"
#: xpack/plugins/cloud/models.py:142 #: xpack/plugins/cloud/models.py:143
msgid "Date last sync" msgid "Date last sync"
msgstr "最后同步日期" msgstr "最后同步日期"
#: xpack/plugins/cloud/models.py:153 xpack/plugins/cloud/models.py:210 #: xpack/plugins/cloud/models.py:154 xpack/plugins/cloud/models.py:207
msgid "Sync instance task" msgid "Sync instance task"
msgstr "同步实例任务" msgstr "同步实例任务"
#: xpack/plugins/cloud/models.py:220 xpack/plugins/cloud/models.py:275 #: xpack/plugins/cloud/models.py:217 xpack/plugins/cloud/models.py:272
msgid "Date sync" msgid "Date sync"
msgstr "同步日期" msgstr "同步日期"
#: xpack/plugins/cloud/models.py:248 #: xpack/plugins/cloud/models.py:245
msgid "Unsync" msgid "Unsync"
msgstr "未同步" msgstr "未同步"
#: xpack/plugins/cloud/models.py:249 xpack/plugins/cloud/models.py:250 #: xpack/plugins/cloud/models.py:246 xpack/plugins/cloud/models.py:247
msgid "Synced" msgid "Synced"
msgstr "已同步" msgstr "已同步"
#: xpack/plugins/cloud/models.py:251 #: xpack/plugins/cloud/models.py:248
msgid "Released" msgid "Released"
msgstr "已释放" msgstr "已释放"
#: xpack/plugins/cloud/models.py:256 #: xpack/plugins/cloud/models.py:253
msgid "Sync task" msgid "Sync task"
msgstr "同步任务" msgstr "同步任务"
#: xpack/plugins/cloud/models.py:260 #: xpack/plugins/cloud/models.py:257
msgid "Sync instance task history" msgid "Sync instance task history"
msgstr "同步实例任务历史" msgstr "同步实例任务历史"
#: xpack/plugins/cloud/models.py:263 #: xpack/plugins/cloud/models.py:260
msgid "Instance" msgid "Instance"
msgstr "实例" msgstr "实例"
#: xpack/plugins/cloud/models.py:266 #: xpack/plugins/cloud/models.py:263
msgid "Region" msgid "Region"
msgstr "地域" msgstr "地域"
#: xpack/plugins/cloud/providers/aliyun.py:19 #: xpack/plugins/cloud/providers/aliyun.py:22
msgid "Alibaba Cloud" msgid "Alibaba Cloud"
msgstr "阿里云" msgstr "阿里云"
#: xpack/plugins/cloud/providers/aws.py:15 #: xpack/plugins/cloud/providers/aws.py:18
msgid "AWS (International)" msgid "AWS (International)"
msgstr "AWS (国际)" msgstr "AWS (国际)"
@ -3788,63 +3800,63 @@ msgstr "AWS (国际)"
msgid "AWS (China)" msgid "AWS (China)"
msgstr "AWS (中国)" msgstr "AWS (中国)"
#: xpack/plugins/cloud/providers/huaweicloud.py:17 #: xpack/plugins/cloud/providers/huaweicloud.py:20
msgid "Huawei Cloud" msgid "Huawei Cloud"
msgstr "华为云" msgstr "华为云"
#: xpack/plugins/cloud/providers/huaweicloud.py:20 #: xpack/plugins/cloud/providers/huaweicloud.py:23
msgid "AF-Johannesburg" msgid "AF-Johannesburg"
msgstr "非洲-约翰内斯堡" msgstr "非洲-约翰内斯堡"
#: xpack/plugins/cloud/providers/huaweicloud.py:21 #: xpack/plugins/cloud/providers/huaweicloud.py:24
msgid "AP-Bangkok" msgid "AP-Bangkok"
msgstr "亚太-曼谷" msgstr "亚太-曼谷"
#: xpack/plugins/cloud/providers/huaweicloud.py:22 #: xpack/plugins/cloud/providers/huaweicloud.py:25
msgid "AP-Hong Kong" msgid "AP-Hong Kong"
msgstr "亚太-香港" msgstr "亚太-香港"
#: xpack/plugins/cloud/providers/huaweicloud.py:23 #: xpack/plugins/cloud/providers/huaweicloud.py:26
msgid "AP-Singapore" msgid "AP-Singapore"
msgstr "亚太-新加坡" msgstr "亚太-新加坡"
#: xpack/plugins/cloud/providers/huaweicloud.py:24 #: xpack/plugins/cloud/providers/huaweicloud.py:27
msgid "CN East-Shanghai1" msgid "CN East-Shanghai1"
msgstr "华东-上海1" msgstr "华东-上海1"
#: xpack/plugins/cloud/providers/huaweicloud.py:25 #: xpack/plugins/cloud/providers/huaweicloud.py:28
msgid "CN East-Shanghai2" msgid "CN East-Shanghai2"
msgstr "华东-上海2" msgstr "华东-上海2"
#: xpack/plugins/cloud/providers/huaweicloud.py:26 #: xpack/plugins/cloud/providers/huaweicloud.py:29
msgid "CN North-Beijing1" msgid "CN North-Beijing1"
msgstr "华北-北京1" msgstr "华北-北京1"
#: xpack/plugins/cloud/providers/huaweicloud.py:27 #: xpack/plugins/cloud/providers/huaweicloud.py:30
msgid "CN North-Beijing4" msgid "CN North-Beijing4"
msgstr "华北-北京4" msgstr "华北-北京4"
#: xpack/plugins/cloud/providers/huaweicloud.py:28 #: xpack/plugins/cloud/providers/huaweicloud.py:31
msgid "CN Northeast-Dalian" msgid "CN Northeast-Dalian"
msgstr "华北-大连" msgstr "华北-大连"
#: xpack/plugins/cloud/providers/huaweicloud.py:29 #: xpack/plugins/cloud/providers/huaweicloud.py:32
msgid "CN South-Guangzhou" msgid "CN South-Guangzhou"
msgstr "华南-广州" msgstr "华南-广州"
#: xpack/plugins/cloud/providers/huaweicloud.py:30 #: xpack/plugins/cloud/providers/huaweicloud.py:33
msgid "CN Southwest-Guiyang1" msgid "CN Southwest-Guiyang1"
msgstr "西南-贵阳1" msgstr "西南-贵阳1"
#: xpack/plugins/cloud/providers/huaweicloud.py:31 #: xpack/plugins/cloud/providers/huaweicloud.py:34
msgid "EU-Paris" msgid "EU-Paris"
msgstr "欧洲-巴黎" msgstr "欧洲-巴黎"
#: xpack/plugins/cloud/providers/huaweicloud.py:32 #: xpack/plugins/cloud/providers/huaweicloud.py:35
msgid "LA-Santiago" msgid "LA-Santiago"
msgstr "拉美-圣地亚哥" msgstr "拉美-圣地亚哥"
#: xpack/plugins/cloud/providers/qcloud.py:17 #: xpack/plugins/cloud/providers/qcloud.py:20
msgid "Tencent Cloud" msgid "Tencent Cloud"
msgstr "腾讯云" msgstr "腾讯云"
@ -3856,11 +3868,7 @@ msgstr "执行次数"
msgid "Instance count" msgid "Instance count"
msgstr "实例个数" msgstr "实例个数"
#: xpack/plugins/cloud/serializers.py:78 #: xpack/plugins/cloud/serializers.py:84
msgid "Account name"
msgstr "账户名称"
#: xpack/plugins/cloud/serializers.py:79
#: xpack/plugins/gathered_user/serializers.py:20 #: xpack/plugins/gathered_user/serializers.py:20
msgid "Periodic display" msgid "Periodic display"
msgstr "定时执行" msgstr "定时执行"
@ -3949,12 +3957,15 @@ msgstr "企业版"
msgid "Ultimate edition" msgid "Ultimate edition"
msgstr "旗舰版" msgstr "旗舰版"
#~ msgid "Covered always"
#~ msgstr "总是被覆盖"
#~ msgid "Account name"
#~ msgstr "账户名称"
#~ msgid "Auditors cannot be join in the user group" #~ msgid "Auditors cannot be join in the user group"
#~ msgstr "审计员不能被加入到用户组" #~ msgstr "审计员不能被加入到用户组"
#~ msgid "Always update"
#~ msgstr "总是更新"
#~ msgid "Target URL" #~ msgid "Target URL"
#~ msgstr "目标URL" #~ msgstr "目标URL"
@ -5097,9 +5108,6 @@ msgstr "旗舰版"
#~ msgid "There is no command about this session" #~ msgid "There is no command about this session"
#~ msgstr "该会话没有命令记录" #~ msgstr "该会话没有命令记录"
#~ msgid "Login from"
#~ msgstr "登录来源"
#~ msgid "Replay session" #~ msgid "Replay session"
#~ msgstr "回放会话" #~ msgstr "回放会话"

View File

@ -2,6 +2,7 @@
# #
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext as _
from rest_framework import status, generics from rest_framework import status, generics
from rest_framework.views import Response from rest_framework.views import Response
from rest_framework_bulk import BulkModelViewSet from rest_framework_bulk import BulkModelViewSet
@ -53,10 +54,12 @@ class OrgViewSet(BulkModelViewSet):
for model in models: for model in models:
data = self.get_data_from_model(model) data = self.get_data_from_model(model)
if data: if data:
return Response(status=status.HTTP_400_BAD_REQUEST) msg = _('Organization contains undeleted resources')
return Response(data={'error': msg}, status=status.HTTP_403_FORBIDDEN)
else: else:
if str(current_org) == str(self.org): if str(current_org) == str(self.org):
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED) msg = _('The current organization cannot be deleted')
return Response(data={'error': msg}, status=status.HTTP_403_FORBIDDEN)
self.org.delete() self.org.delete()
return Response({'msg': True}, status=status.HTTP_200_OK) return Response({'msg': True}, status=status.HTTP_200_OK)

View File

@ -43,4 +43,7 @@ def on_create_set_created_by(sender, instance=None, **kwargs):
return return
if hasattr(instance, 'created_by') and not instance.created_by: if hasattr(instance, 'created_by') and not instance.created_by:
if current_request and current_request.user.is_authenticated: if current_request and current_request.user.is_authenticated:
instance.created_by = current_request.user.name user_name = current_request.user.name
if isinstance(user_name, str):
user_name = user_name[:30]
instance.created_by = user_name

View File

@ -55,21 +55,17 @@ class CommandQueryMixin:
q = self.request.query_params q = self.request.query_params
multi_command_storage = get_multi_command_storage() multi_command_storage = get_multi_command_storage()
queryset = multi_command_storage.filter( queryset = multi_command_storage.filter(
date_from=date_from, date_to=date_to, input=q.get("input"), date_from=date_from, date_to=date_to,
user=q.get("user"), asset=q.get("asset"), user=q.get("user"), asset=q.get("asset"), system_user=q.get("system_user"),
system_user=q.get("system_user"), input=q.get("input"), session=q.get("session_id"),
risk_level=self.get_query_risk_level(), org_id=self.get_org_id(), risk_level=self.get_query_risk_level(), org_id=self.get_org_id(),
) )
return queryset return queryset
def filter_queryset(self, queryset): def filter_queryset(self, queryset):
# 解决es存储命令时父类根据filter_fields过滤出现异常的问题返回的queryset类型list
return queryset return queryset
def get_filter_fields(self, request):
fields = self.filter_fields
fields.extend(["date_from", "date_to"])
return fields
def get_date_range(self): def get_date_range(self):
now = timezone.now() now = timezone.now()
days_ago = now - timezone.timedelta(days=self.default_days_ago) days_ago = now - timezone.timedelta(days=self.default_days_ago)

View File

@ -44,7 +44,7 @@ class SessionViewSet(OrgBulkModelViewSet):
permission_classes = (IsOrgAdminOrAppUser, ) permission_classes = (IsOrgAdminOrAppUser, )
filter_fields = [ filter_fields = [
"user", "asset", "system_user", "remote_addr", "user", "asset", "system_user", "remote_addr",
"protocol", "terminal", "is_finished", "protocol", "terminal", "is_finished", 'login_from',
] ]
date_range_filter_fields = [ date_range_filter_fields = [
('date_start', ('date_from', 'date_to')) ('date_start', ('date_from', 'date_to'))

View File

@ -16,7 +16,7 @@ class CommandBase(object):
@abc.abstractmethod @abc.abstractmethod
def filter(self, date_from=None, date_to=None, def filter(self, date_from=None, date_to=None,
user=None, asset=None, system_user=None, user=None, asset=None, system_user=None,
input=None, session=None): input=None, session=None, risk_level=None, org_id=None):
pass pass
@abc.abstractmethod @abc.abstractmethod

View File

@ -0,0 +1,18 @@
# Generated by Django 2.2.10 on 2020-07-15 09:13
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('terminal', '0023_command_risk_level'),
]
operations = [
migrations.AlterField(
model_name='session',
name='login_from',
field=models.CharField(choices=[('ST', 'SSH Terminal'), ('WT', 'Web Terminal')], default='ST', max_length=2, verbose_name='Login from'),
),
]

View File

@ -188,7 +188,7 @@ class Session(OrgModelMixin):
asset_id = models.CharField(blank=True, default='', max_length=36, db_index=True) asset_id = models.CharField(blank=True, default='', max_length=36, db_index=True)
system_user = models.CharField(max_length=128, verbose_name=_("System user"), db_index=True) system_user = models.CharField(max_length=128, verbose_name=_("System user"), db_index=True)
system_user_id = models.CharField(blank=True, default='', max_length=36, db_index=True) system_user_id = models.CharField(blank=True, default='', max_length=36, db_index=True)
login_from = models.CharField(max_length=2, choices=LOGIN_FROM_CHOICES, default="ST") login_from = models.CharField(max_length=2, choices=LOGIN_FROM_CHOICES, default="ST", verbose_name=_("Login from"))
remote_addr = models.CharField(max_length=128, verbose_name=_("Remote addr"), blank=True, null=True) remote_addr = models.CharField(max_length=128, verbose_name=_("Remote addr"), blank=True, null=True)
is_success = models.BooleanField(default=True, db_index=True) is_success = models.BooleanField(default=True, db_index=True)
is_finished = models.BooleanField(default=False, db_index=True) is_finished = models.BooleanField(default=False, db_index=True)

View File

@ -7,7 +7,7 @@ from .. import api
app_name = 'tickets' app_name = 'tickets'
router = BulkRouter() router = BulkRouter()
router.register('tickets/request-asset-perm', api.RequestAssetPermTicketViewSet, 'ticket-request-asset-perm') # router.register('tickets/request-asset-perm', api.RequestAssetPermTicketViewSet, 'ticket-request-asset-perm')
router.register('tickets', api.TicketViewSet, 'ticket') router.register('tickets', api.TicketViewSet, 'ticket')
router.register('tickets/(?P<ticket_id>[0-9a-zA-Z\-]{36})/comments', api.TicketCommentViewSet, 'ticket-comment') router.register('tickets/(?P<ticket_id>[0-9a-zA-Z\-]{36})/comments', api.TicketCommentViewSet, 'ticket-comment')

View File

@ -87,7 +87,11 @@ class UserSerializer(CommonBulkSerializerMixin, serializers.ModelSerializer):
if not role: if not role:
return return
choices = role._choices choices = role._choices
choices.pop('App', None) choices.pop(User.ROLE_APP, None)
request = self.context.get('request')
if request and hasattr(request, 'user') and not request.user.is_superuser:
choices.pop(User.ROLE_ADMIN, None)
choices.pop(User.ROLE_AUDITOR, None)
role._choices = choices role._choices = choices
def validate_role(self, value): def validate_role(self, value):

2
jms
View File

@ -217,7 +217,7 @@ def get_start_celery_ansible_kwargs():
def get_start_celery_default_kwargs(): def get_start_celery_default_kwargs():
print("\n- Start Celery as Distributed Task Queue: Celery") print("\n- Start Celery as Distributed Task Queue: Celery")
return get_start_worker_kwargs('celery', 2) return get_start_worker_kwargs('celery', 4)
def get_start_worker_kwargs(queue, num): def get_start_worker_kwargs(queue, num):