diff --git a/apps/assets/migrations/0050_auto_20200711_1740.py b/apps/assets/migrations/0050_auto_20200711_1740.py new file mode 100644 index 000000000..231fcfbe4 --- /dev/null +++ b/apps/assets/migrations/0050_auto_20200711_1740.py @@ -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'), + ), + ] diff --git a/apps/assets/migrations/0050_auto_20200702_1602.py b/apps/assets/migrations/0051_auto_20200713_1143.py similarity index 81% rename from apps/assets/migrations/0050_auto_20200702_1602.py rename to apps/assets/migrations/0051_auto_20200713_1143.py index 5471003ae..95ec1ca06 100644 --- a/apps/assets/migrations/0050_auto_20200702_1602.py +++ b/apps/assets/migrations/0051_auto_20200713_1143.py @@ -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 @@ -6,7 +6,7 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('assets', '0049_systemuser_sftp_root'), + ('assets', '0050_auto_20200711_1740'), ] operations = [ diff --git a/apps/assets/migrations/0052_auto_20200715_1535.py b/apps/assets/migrations/0052_auto_20200715_1535.py new file mode 100644 index 000000000..5903d635e --- /dev/null +++ b/apps/assets/migrations/0052_auto_20200715_1535.py @@ -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')}, + ), + ] diff --git a/apps/assets/models/asset.py b/apps/assets/models/asset.py index 6b5e716e0..82d09944c 100644 --- a/apps/assets/models/asset.py +++ b/apps/assets/models/asset.py @@ -221,7 +221,7 @@ class Asset(ProtocolsMixin, NodesRelationMixin, OrgModelMixin): 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")) - 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')) comment = models.TextField(max_length=128, default='', blank=True, verbose_name=_('Comment')) diff --git a/apps/assets/models/authbook.py b/apps/assets/models/authbook.py index 052b83a64..7d0a3f472 100644 --- a/apps/assets/models/authbook.py +++ b/apps/assets/models/authbook.py @@ -3,7 +3,6 @@ from django.db import models, transaction from django.db.models import Max -from django.core.cache import cache from django.utils.translation import ugettext_lazy as _ from orgs.mixins.models import OrgManager @@ -59,19 +58,17 @@ class AuthBook(BaseUser): """ username = kwargs['username'] asset = kwargs['asset'] - key_lock = 'KEY_LOCK_CREATE_AUTH_BOOK_{}_{}'.format(username, asset.id) - with cache.lock(key_lock): - with transaction.atomic(): - cls.objects.filter( - username=username, asset=asset, is_latest=True - ).update(is_latest=False) - max_version = cls.get_max_version(username, asset) - kwargs.update({ - 'version': max_version + 1, - 'is_latest': True - }) - obj = cls.objects.create(**kwargs) - return obj + with transaction.atomic(): + # 使用select_for_update限制并发创建相同的username、asset条目 + instances = cls.objects.select_for_update().filter(username=username, asset=asset) + instances.filter(is_latest=True).update(is_latest=False) + max_version = cls.get_max_version(username, asset) + kwargs.update({ + 'version': max_version + 1, + 'is_latest': True + }) + obj = cls.objects.create(**kwargs) + return obj @property def connectivity(self): diff --git a/apps/assets/models/cmd_filter.py b/apps/assets/models/cmd_filter.py index 91febd40b..d7707115d 100644 --- a/apps/assets/models/cmd_filter.py +++ b/apps/assets/models/cmd_filter.py @@ -18,7 +18,7 @@ __all__ = [ class CommandFilter(OrgModelMixin): 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')) comment = models.TextField(blank=True, default='', verbose_name=_("Comment")) date_created = models.DateTimeField(auto_now_add=True) @@ -29,6 +29,7 @@ class CommandFilter(OrgModelMixin): return self.name class Meta: + unique_together = [('org_id', 'name')] verbose_name = _("Command filter") diff --git a/apps/assets/signals_handler.py b/apps/assets/signals_handler.py index ce906dcd2..f3329c286 100644 --- a/apps/assets/signals_handler.py +++ b/apps/assets/signals_handler.py @@ -185,7 +185,9 @@ def on_asset_nodes_add(sender, instance=None, action='', model=None, pk_set=None system_users_assets = defaultdict(set) 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(): system_user.assets.add(*tuple(_assets)) diff --git a/apps/assets/tasks/const.py b/apps/assets/tasks/const.py index ce9ad9074..51f92bd51 100644 --- a/apps/assets/tasks/const.py +++ b/apps/assets/tasks/const.py @@ -64,7 +64,7 @@ GATHER_ASSET_USERS_TASKS = [ "action": { "module": "shell", "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" } } diff --git a/apps/audits/serializers.py b/apps/audits/serializers.py index 23d562c8d..cc954640d 100644 --- a/apps/audits/serializers.py +++ b/apps/audits/serializers.py @@ -17,7 +17,7 @@ class FTPLogSerializer(serializers.ModelSerializer): class Meta: model = models.FTPLog 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' ) @@ -40,7 +40,7 @@ class OperateLogSerializer(serializers.ModelSerializer): model = models.OperateLog fields = ( '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_small = fields_mini + [ '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'] extra_kwargs = { diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 9663de119..0337649da 100644 Binary files a/apps/locale/zh/LC_MESSAGES/django.mo and b/apps/locale/zh/LC_MESSAGES/django.mo differ diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 1d1005ab4..c311e0a7f 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\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" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -85,7 +85,7 @@ msgstr "数据库" #: users/templates/users/user_group_list.html:16 #: users/templates/users/user_profile.html:138 #: 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" msgstr "备注" @@ -100,7 +100,7 @@ msgid "DatabaseApp" msgstr "数据库应用" #: 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/asset_user.py:84 assets/serializers/system_user.py:44 #: 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_granted_remote_app.html:36 #: xpack/plugins/change_auth_plan/models.py:283 -#: xpack/plugins/cloud/models.py:269 +#: xpack/plugins/cloud/models.py:266 msgid "Asset" msgstr "资产" @@ -135,7 +135,7 @@ msgstr "参数" #: perms/models/base.py:54 users/models/user.py:508 #: 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/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" msgstr "创建者" @@ -148,7 +148,7 @@ msgstr "创建者" #: 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 #: 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" msgstr "创建日期" @@ -247,7 +247,7 @@ msgstr "激活" #: assets/models/asset.py:199 assets/models/cluster.py:19 #: 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" msgstr "管理用户" @@ -319,19 +319,19 @@ msgstr "主机名原始" msgid "Labels" msgstr "标签管理" -#: assets/models/authbook.py:18 +#: assets/models/authbook.py:17 msgid "Bulk delete deny" msgstr "拒绝批量删除" -#: assets/models/authbook.py:28 +#: assets/models/authbook.py:27 msgid "Latest version" msgstr "最新版本" -#: assets/models/authbook.py:29 +#: assets/models/authbook.py:28 msgid "Version" msgstr "版本" -#: assets/models/authbook.py:38 +#: assets/models/authbook.py:37 msgid "AuthBook" msgstr "" @@ -590,7 +590,7 @@ msgstr "键" #: users/templates/users/user_asset_permission.html:41 #: users/templates/users/user_asset_permission.html:73 #: 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" msgstr "节点" @@ -612,7 +612,7 @@ msgid "Assets" msgstr "资产管理" #: 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" msgstr "用户管理" @@ -874,7 +874,7 @@ msgstr "没有匹配到资产,结束任务" #: users/templates/users/user_list.html:98 #: users/templates/users/user_remote_app_permission.html:111 msgid "Delete" -msgstr "删除文件" +msgstr "删除" #: audits/models.py:27 msgid "Upload" @@ -976,7 +976,7 @@ msgstr "启用" msgid "-" msgstr "" -#: audits/models.py:96 xpack/plugins/cloud/models.py:204 +#: audits/models.py:96 xpack/plugins/cloud/models.py:201 msgid "Failed" msgstr "失败" @@ -1006,13 +1006,13 @@ msgid "MFA" msgstr "多因子认证" #: 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" msgstr "原因" #: audits/models.py:106 tickets/serializers/request_asset_perm.py:53 -#: tickets/serializers/ticket.py:25 xpack/plugins/cloud/models.py:214 -#: xpack/plugins/cloud/models.py:272 +#: tickets/serializers/ticket.py:25 xpack/plugins/cloud/models.py:211 +#: xpack/plugins/cloud/models.py:269 msgid "Status" msgstr "状态" @@ -1025,7 +1025,7 @@ msgid "Is success" msgstr "是否成功" #: audits/serializers.py:73 ops/models/command.py:24 -#: xpack/plugins/cloud/models.py:212 +#: xpack/plugins/cloud/models.py:209 msgid "Result" msgstr "结果" @@ -1144,8 +1144,8 @@ msgid "" "after {} minutes)" msgstr "账号已被锁定(请联系管理员解锁 或 {}分钟后重试)" -#: authentication/errors.py:50 users/views/profile/otp.py:63 -#: users/views/profile/otp.py:102 users/views/profile/otp.py:121 +#: authentication/errors.py:50 users/views/profile/otp.py:107 +#: users/views/profile/otp.py:146 users/views/profile/otp.py:166 msgid "MFA code invalid, or ntp sync server time" msgstr "MFA验证码不正确,或者服务器端时间不对" @@ -1440,10 +1440,6 @@ msgstr "字段必须唯一" msgid "

Flow service unavailable, check it

" msgstr "" -#: jumpserver/views/index.py:26 templates/_nav.html:7 -msgid "Dashboard" -msgstr "仪表盘" - #: jumpserver/views/other.py:26 msgid "" "
Luna is a separately deployed program, you need to deploy Luna, koko, " @@ -1626,6 +1622,14 @@ msgstr "更新任务内容: {}" msgid "Disk used more than 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 msgid "Organization" msgstr "组织" @@ -2019,6 +2023,10 @@ msgstr "" "\"%(user_pubkey_update)s\"> 链接 更新\n" " " +#: templates/_nav.html:7 +msgid "Dashboard" +msgstr "仪表盘" + #: templates/_nav.html:20 msgid "User list" msgstr "用户列表" @@ -2421,6 +2429,10 @@ msgstr "线程数" msgid "Boot Time" msgstr "运行时间" +#: terminal/models.py:191 +msgid "Login from" +msgstr "登录来源" + #: terminal/models.py:195 msgid "Replay" msgstr "回放" @@ -2433,11 +2445,11 @@ msgstr "结束日期" msgid "Args" msgstr "参数" -#: tickets/api/request_asset_perm.py:40 +#: tickets/api/request_asset_perm.py:41 msgid "Ticket closed" msgstr "工单已关闭" -#: tickets/api/request_asset_perm.py:43 +#: tickets/api/request_asset_perm.py:44 #, python-format msgid "Ticket has %s" msgstr "工单已%s" @@ -2446,27 +2458,27 @@ msgstr "工单已%s" msgid "Superuser" msgstr "超级管理员" -#: tickets/api/request_asset_perm.py:102 +#: tickets/api/request_asset_perm.py:99 msgid "Confirm assets first" msgstr "请先确认资产" -#: tickets/api/request_asset_perm.py:105 +#: tickets/api/request_asset_perm.py:102 msgid "Confirmed assets changed" msgstr "确认的资产变更了" -#: tickets/api/request_asset_perm.py:109 +#: tickets/api/request_asset_perm.py:106 msgid "Confirm system-user first" msgstr "请先确认系统用户" -#: tickets/api/request_asset_perm.py:113 +#: tickets/api/request_asset_perm.py:110 msgid "Confirmed system-user changed" 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" msgstr "成功" -#: tickets/api/request_asset_perm.py:124 +#: tickets/api/request_asset_perm.py:121 msgid "{} request assets, approved by {}" msgstr "{} 申请资产,通过人 {}" @@ -2720,7 +2732,7 @@ msgstr "复制用户公钥到这里" msgid "Join user groups" 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 msgid "* Your password does not meet the requirements" msgstr "* 您的密码不符合要求" @@ -2837,7 +2849,7 @@ msgstr "安全令牌验证" #: users/templates/users/_base_otp.html:14 users/templates/users/_user.html:13 #: 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" msgstr "账户" @@ -3552,27 +3564,27 @@ msgstr "" "
\n" " " -#: users/views/profile/otp.py:145 +#: users/views/profile/otp.py:190 msgid "MFA enable success" msgstr "多因子认证启用成功" -#: users/views/profile/otp.py:146 +#: users/views/profile/otp.py:191 msgid "MFA enable success, return login page" msgstr "多因子认证启用成功,返回到登录页面" -#: users/views/profile/otp.py:148 +#: users/views/profile/otp.py:193 msgid "MFA disable success" msgstr "多因子认证禁用成功" -#: users/views/profile/otp.py:149 +#: users/views/profile/otp.py:194 msgid "MFA disable success, return login page" msgstr "多因子认证禁用成功,返回登录页面" -#: users/views/profile/password.py:41 +#: users/views/profile/password.py:43 msgid "Password update" msgstr "密码更新" -#: users/views/profile/password.py:72 +#: users/views/profile/password.py:74 msgid "Password invalid" msgstr "用户名或密码无效" @@ -3732,55 +3744,55 @@ msgstr "地域" msgid "Instances" msgstr "实例" -#: xpack/plugins/cloud/models.py:136 xpack/plugins/cloud/serializers.py:80 -msgid "Covered always" -msgstr "总是被覆盖" +#: xpack/plugins/cloud/models.py:137 xpack/plugins/cloud/serializers.py:85 +msgid "Always update" +msgstr "总是更新" -#: xpack/plugins/cloud/models.py:142 +#: xpack/plugins/cloud/models.py:143 msgid "Date last sync" 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" 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" msgstr "同步日期" -#: xpack/plugins/cloud/models.py:248 +#: xpack/plugins/cloud/models.py:245 msgid "Unsync" 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" msgstr "已同步" -#: xpack/plugins/cloud/models.py:251 +#: xpack/plugins/cloud/models.py:248 msgid "Released" msgstr "已释放" -#: xpack/plugins/cloud/models.py:256 +#: xpack/plugins/cloud/models.py:253 msgid "Sync task" msgstr "同步任务" -#: xpack/plugins/cloud/models.py:260 +#: xpack/plugins/cloud/models.py:257 msgid "Sync instance task history" msgstr "同步实例任务历史" -#: xpack/plugins/cloud/models.py:263 +#: xpack/plugins/cloud/models.py:260 msgid "Instance" msgstr "实例" -#: xpack/plugins/cloud/models.py:266 +#: xpack/plugins/cloud/models.py:263 msgid "Region" msgstr "地域" -#: xpack/plugins/cloud/providers/aliyun.py:19 +#: xpack/plugins/cloud/providers/aliyun.py:22 msgid "Alibaba Cloud" msgstr "阿里云" -#: xpack/plugins/cloud/providers/aws.py:15 +#: xpack/plugins/cloud/providers/aws.py:18 msgid "AWS (International)" msgstr "AWS (国际)" @@ -3788,63 +3800,63 @@ msgstr "AWS (国际)" msgid "AWS (China)" msgstr "AWS (中国)" -#: xpack/plugins/cloud/providers/huaweicloud.py:17 +#: xpack/plugins/cloud/providers/huaweicloud.py:20 msgid "Huawei Cloud" msgstr "华为云" -#: xpack/plugins/cloud/providers/huaweicloud.py:20 +#: xpack/plugins/cloud/providers/huaweicloud.py:23 msgid "AF-Johannesburg" msgstr "非洲-约翰内斯堡" -#: xpack/plugins/cloud/providers/huaweicloud.py:21 +#: xpack/plugins/cloud/providers/huaweicloud.py:24 msgid "AP-Bangkok" msgstr "亚太-曼谷" -#: xpack/plugins/cloud/providers/huaweicloud.py:22 +#: xpack/plugins/cloud/providers/huaweicloud.py:25 msgid "AP-Hong Kong" msgstr "亚太-香港" -#: xpack/plugins/cloud/providers/huaweicloud.py:23 +#: xpack/plugins/cloud/providers/huaweicloud.py:26 msgid "AP-Singapore" msgstr "亚太-新加坡" -#: xpack/plugins/cloud/providers/huaweicloud.py:24 +#: xpack/plugins/cloud/providers/huaweicloud.py:27 msgid "CN East-Shanghai1" msgstr "华东-上海1" -#: xpack/plugins/cloud/providers/huaweicloud.py:25 +#: xpack/plugins/cloud/providers/huaweicloud.py:28 msgid "CN East-Shanghai2" msgstr "华东-上海2" -#: xpack/plugins/cloud/providers/huaweicloud.py:26 +#: xpack/plugins/cloud/providers/huaweicloud.py:29 msgid "CN North-Beijing1" msgstr "华北-北京1" -#: xpack/plugins/cloud/providers/huaweicloud.py:27 +#: xpack/plugins/cloud/providers/huaweicloud.py:30 msgid "CN North-Beijing4" msgstr "华北-北京4" -#: xpack/plugins/cloud/providers/huaweicloud.py:28 +#: xpack/plugins/cloud/providers/huaweicloud.py:31 msgid "CN Northeast-Dalian" msgstr "华北-大连" -#: xpack/plugins/cloud/providers/huaweicloud.py:29 +#: xpack/plugins/cloud/providers/huaweicloud.py:32 msgid "CN South-Guangzhou" msgstr "华南-广州" -#: xpack/plugins/cloud/providers/huaweicloud.py:30 +#: xpack/plugins/cloud/providers/huaweicloud.py:33 msgid "CN Southwest-Guiyang1" msgstr "西南-贵阳1" -#: xpack/plugins/cloud/providers/huaweicloud.py:31 +#: xpack/plugins/cloud/providers/huaweicloud.py:34 msgid "EU-Paris" msgstr "欧洲-巴黎" -#: xpack/plugins/cloud/providers/huaweicloud.py:32 +#: xpack/plugins/cloud/providers/huaweicloud.py:35 msgid "LA-Santiago" msgstr "拉美-圣地亚哥" -#: xpack/plugins/cloud/providers/qcloud.py:17 +#: xpack/plugins/cloud/providers/qcloud.py:20 msgid "Tencent Cloud" msgstr "腾讯云" @@ -3856,11 +3868,7 @@ msgstr "执行次数" msgid "Instance count" msgstr "实例个数" -#: xpack/plugins/cloud/serializers.py:78 -msgid "Account name" -msgstr "账户名称" - -#: xpack/plugins/cloud/serializers.py:79 +#: xpack/plugins/cloud/serializers.py:84 #: xpack/plugins/gathered_user/serializers.py:20 msgid "Periodic display" msgstr "定时执行" @@ -3949,12 +3957,15 @@ msgstr "企业版" msgid "Ultimate edition" msgstr "旗舰版" +#~ msgid "Covered always" +#~ msgstr "总是被覆盖" + +#~ msgid "Account name" +#~ msgstr "账户名称" + #~ msgid "Auditors cannot be join in the user group" #~ msgstr "审计员不能被加入到用户组" -#~ msgid "Always update" -#~ msgstr "总是更新" - #~ msgid "Target URL" #~ msgstr "目标URL" @@ -5097,9 +5108,6 @@ msgstr "旗舰版" #~ msgid "There is no command about this session" #~ msgstr "该会话没有命令记录" -#~ msgid "Login from" -#~ msgstr "登录来源" - #~ msgid "Replay session" #~ msgstr "回放会话" diff --git a/apps/orgs/api.py b/apps/orgs/api.py index 448c1dab0..d8ba32635 100644 --- a/apps/orgs/api.py +++ b/apps/orgs/api.py @@ -2,6 +2,7 @@ # from django.shortcuts import get_object_or_404 +from django.utils.translation import ugettext as _ from rest_framework import status, generics from rest_framework.views import Response from rest_framework_bulk import BulkModelViewSet @@ -53,10 +54,12 @@ class OrgViewSet(BulkModelViewSet): for model in models: data = self.get_data_from_model(model) 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: 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() return Response({'msg': True}, status=status.HTTP_200_OK) diff --git a/apps/settings/signals_handler.py b/apps/settings/signals_handler.py index 026d60a78..94c4569bd 100644 --- a/apps/settings/signals_handler.py +++ b/apps/settings/signals_handler.py @@ -43,4 +43,7 @@ def on_create_set_created_by(sender, instance=None, **kwargs): return if hasattr(instance, 'created_by') and not instance.created_by: 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 diff --git a/apps/terminal/api/command.py b/apps/terminal/api/command.py index 749da4fcb..d18c70858 100644 --- a/apps/terminal/api/command.py +++ b/apps/terminal/api/command.py @@ -55,21 +55,17 @@ class CommandQueryMixin: q = self.request.query_params multi_command_storage = get_multi_command_storage() queryset = multi_command_storage.filter( - date_from=date_from, date_to=date_to, input=q.get("input"), - user=q.get("user"), asset=q.get("asset"), - system_user=q.get("system_user"), + date_from=date_from, date_to=date_to, + user=q.get("user"), asset=q.get("asset"), 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(), ) return queryset def filter_queryset(self, queryset): + # 解决es存储命令时,父类根据filter_fields过滤出现异常的问题,返回的queryset类型list 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): now = timezone.now() days_ago = now - timezone.timedelta(days=self.default_days_ago) diff --git a/apps/terminal/api/session.py b/apps/terminal/api/session.py index f340147c3..bf0a69789 100644 --- a/apps/terminal/api/session.py +++ b/apps/terminal/api/session.py @@ -44,7 +44,7 @@ class SessionViewSet(OrgBulkModelViewSet): permission_classes = (IsOrgAdminOrAppUser, ) filter_fields = [ "user", "asset", "system_user", "remote_addr", - "protocol", "terminal", "is_finished", + "protocol", "terminal", "is_finished", 'login_from', ] date_range_filter_fields = [ ('date_start', ('date_from', 'date_to')) diff --git a/apps/terminal/backends/command/base.py b/apps/terminal/backends/command/base.py index d95697ed0..4bb85e127 100644 --- a/apps/terminal/backends/command/base.py +++ b/apps/terminal/backends/command/base.py @@ -16,7 +16,7 @@ class CommandBase(object): @abc.abstractmethod def filter(self, date_from=None, date_to=None, user=None, asset=None, system_user=None, - input=None, session=None): + input=None, session=None, risk_level=None, org_id=None): pass @abc.abstractmethod diff --git a/apps/terminal/migrations/0024_auto_20200715_1713.py b/apps/terminal/migrations/0024_auto_20200715_1713.py new file mode 100644 index 000000000..b99ad8d79 --- /dev/null +++ b/apps/terminal/migrations/0024_auto_20200715_1713.py @@ -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'), + ), + ] diff --git a/apps/terminal/models.py b/apps/terminal/models.py index a2dcbf8e0..f3914cc1c 100644 --- a/apps/terminal/models.py +++ b/apps/terminal/models.py @@ -188,7 +188,7 @@ class Session(OrgModelMixin): 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_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) is_success = models.BooleanField(default=True, db_index=True) is_finished = models.BooleanField(default=False, db_index=True) diff --git a/apps/tickets/urls/api_urls.py b/apps/tickets/urls/api_urls.py index a7bd3f6e5..b086aa9d3 100644 --- a/apps/tickets/urls/api_urls.py +++ b/apps/tickets/urls/api_urls.py @@ -7,7 +7,7 @@ from .. import api app_name = 'tickets' 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/(?P[0-9a-zA-Z\-]{36})/comments', api.TicketCommentViewSet, 'ticket-comment') diff --git a/apps/users/serializers/user.py b/apps/users/serializers/user.py index 351f33337..bebc5042b 100644 --- a/apps/users/serializers/user.py +++ b/apps/users/serializers/user.py @@ -87,7 +87,11 @@ class UserSerializer(CommonBulkSerializerMixin, serializers.ModelSerializer): if not role: return 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 def validate_role(self, value): diff --git a/jms b/jms index 48110133e..8081af0bb 100755 --- a/jms +++ b/jms @@ -217,7 +217,7 @@ def get_start_celery_ansible_kwargs(): def get_start_celery_default_kwargs(): 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):