diff --git a/apps/assets/api/asset_user.py b/apps/assets/api/asset_user.py
index ce5930a26..c0d834737 100644
--- a/apps/assets/api/asset_user.py
+++ b/apps/assets/api/asset_user.py
@@ -105,7 +105,7 @@ class AssetUserViewSet(CommonApiMixin, BulkModelViewSet):
class AssetUserAuthInfoViewSet(AssetUserViewSet):
serializer_classes = {"default": serializers.AssetUserAuthInfoSerializer}
- http_method_names = ['get']
+ http_method_names = ['get', 'post']
permission_classes = [IsOrgAdminOrAppUser]
def get_permissions(self):
diff --git a/apps/assets/api/system_user_relation.py b/apps/assets/api/system_user_relation.py
index 02dd887a1..69605b74a 100644
--- a/apps/assets/api/system_user_relation.py
+++ b/apps/assets/api/system_user_relation.py
@@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
#
+from collections import defaultdict
from django.db.models import F, Value
+from django.db.models.signals import m2m_changed
from django.db.models.functions import Concat
from common.permissions import IsOrgAdmin
@@ -26,6 +28,34 @@ class RelationMixin:
))
return queryset
+ def send_post_add_signal(self, instance):
+ if not isinstance(instance, list):
+ instance = [instance]
+
+ system_users_objects_map = defaultdict(list)
+ model, object_field = self.get_objects_attr()
+
+ for i in instance:
+ _id = getattr(i, object_field).id
+ system_users_objects_map[i.systemuser].append(_id)
+
+ sender = self.get_sender()
+ for system_user, objects in system_users_objects_map.items():
+ m2m_changed.send(
+ sender=sender, instance=system_user, action='post_add',
+ reverse=False, model=model, pk_set=objects
+ )
+
+ def get_sender(self):
+ return self.model
+
+ def get_objects_attr(self):
+ return models.Asset, 'asset'
+
+ def perform_create(self, serializer):
+ instance = serializer.save()
+ self.send_post_add_signal(instance)
+
class BaseRelationViewSet(RelationMixin, OrgBulkModelViewSet):
pass
@@ -43,6 +73,9 @@ class SystemUserAssetRelationViewSet(BaseRelationViewSet):
"systemuser__name", "systemuser__username"
]
+ def get_objects_attr(self):
+ return models.Asset, 'asset'
+
def get_queryset(self):
queryset = super().get_queryset()
queryset = queryset.annotate(
@@ -65,6 +98,9 @@ class SystemUserNodeRelationViewSet(BaseRelationViewSet):
"node__value", "systemuser__name", "systemuser_username"
]
+ def get_objects_attr(self):
+ return models.Node, 'node'
+
def get_queryset(self):
queryset = super().get_queryset()
queryset = queryset \
@@ -84,6 +120,10 @@ class SystemUserUserRelationViewSet(BaseRelationViewSet):
"systemuser__name", "systemuser__username",
]
+ def get_objects_attr(self):
+ from users.models import User
+ return User, 'user'
+
def get_queryset(self):
queryset = super().get_queryset()
queryset = queryset.annotate(
diff --git a/apps/assets/backends/db.py b/apps/assets/backends/db.py
index 7cdba2754..35be8b9fd 100644
--- a/apps/assets/backends/db.py
+++ b/apps/assets/backends/db.py
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
#
+from django.utils.translation import ugettext as _
from functools import reduce
from django.db.models import F, CharField, Value, IntegerField, Q, Count
from django.db.models.functions import Concat
@@ -240,7 +241,7 @@ class AdminUserBackend(DBBackend):
)
def _perform_delete_by_union_id(self, union_id_cleaned):
- raise PermissionError("Could remove asset admin user")
+ raise PermissionError(_("Could not remove asset admin user"))
def all(self):
qs = self.model.objects.all().annotate(
@@ -301,7 +302,7 @@ class AuthbookBackend(DBBackend):
authbook_id, asset_id = union_id_cleaned
authbook = get_object_or_none(AuthBook, pk=authbook_id)
if authbook.is_latest:
- raise PermissionError("Latest version could be delete")
+ raise PermissionError(_("Latest version could not be delete"))
AuthBook.objects.filter(id=authbook_id).delete()
def all(self):
diff --git a/apps/assets/signals_handler.py b/apps/assets/signals_handler.py
index 696732fc8..3bf185bc4 100644
--- a/apps/assets/signals_handler.py
+++ b/apps/assets/signals_handler.py
@@ -16,6 +16,8 @@ from .tasks import (
update_assets_hardware_info_util,
test_asset_connectivity_util,
push_system_user_to_assets,
+ push_system_user_to_assets_manual,
+ push_system_user_to_assets,
add_nodes_assets_to_system_users
)
@@ -95,6 +97,25 @@ def on_system_user_assets_change(sender, instance=None, action='', model=None, p
push_system_user_to_assets.delay(system_user, assets)
+@receiver(m2m_changed, sender=SystemUser.users.through)
+def on_system_user_users_change(sender, instance=None, action='', model=None, pk_set=None, **kwargs):
+ """
+ 当系统用户和用户关系发生变化时,应该重新推送系统用户资产中
+ """
+ if action != "post_add":
+ return
+ if not instance.username_same_with_user:
+ return
+ logger.debug("System user users change signal recv: {}".format(instance))
+ queryset = model.objects.filter(pk__in=pk_set)
+ if model == SystemUser:
+ system_users = queryset
+ else:
+ system_users = [instance]
+ for s in system_users:
+ push_system_user_to_assets_manual.delay(s)
+
+
@receiver(m2m_changed, sender=SystemUser.nodes.through)
def on_system_user_nodes_change(sender, instance=None, action=None, model=None, pk_set=None, **kwargs):
"""
diff --git a/apps/assets/tasks/push_system_user.py b/apps/assets/tasks/push_system_user.py
index 961f24a01..eb3978178 100644
--- a/apps/assets/tasks/push_system_user.py
+++ b/apps/assets/tasks/push_system_user.py
@@ -121,7 +121,6 @@ def get_push_windows_system_user_tasks(system_user, username=None):
''.format(username, username, password),
}
}
- print(task)
tasks.append(task)
return tasks
@@ -193,10 +192,10 @@ def push_system_user_util(system_user, assets, task_name, username=None):
@shared_task(queue="ansible")
-def push_system_user_to_assets_manual(system_user):
+def push_system_user_to_assets_manual(system_user, username=None):
assets = system_user.get_related_assets()
task_name = _("Push system users to assets: {}").format(system_user.name)
- return push_system_user_util(system_user, assets, task_name=task_name)
+ return push_system_user_util(system_user, assets, task_name=task_name, username=username)
@shared_task(queue="ansible")
@@ -210,9 +209,9 @@ def push_system_user_a_asset_manual(system_user, asset, username=None):
@shared_task(queue="ansible")
-def push_system_user_to_assets(system_user, assets):
+def push_system_user_to_assets(system_user, assets, username=None):
task_name = _("Push system users to assets: {}").format(system_user.name)
- return push_system_user_util(system_user, assets, task_name)
+ return push_system_user_util(system_user, assets, task_name, username=username)
diff --git a/apps/assets/templates/assets/admin_user_detail.html b/apps/assets/templates/assets/admin_user_detail.html
index e3f618d93..198b1e765 100644
--- a/apps/assets/templates/assets/admin_user_detail.html
+++ b/apps/assets/templates/assets/admin_user_detail.html
@@ -61,7 +61,7 @@
{% trans 'Created by' %}: |
- {{ asset_group.created_by }} |
+ {{ admin_user.created_by }} |
{% trans 'Comment' %}: |
diff --git a/apps/assets/templates/assets/asset_list.html b/apps/assets/templates/assets/asset_list.html
index f7588043a..24a789404 100644
--- a/apps/assets/templates/assets/asset_list.html
+++ b/apps/assets/templates/assets/asset_list.html
@@ -258,6 +258,10 @@ $(document).ready(function(){
confirmButtonText: "{% trans 'Confirm' %}",
closeOnConfirm: false
},function () {
+ function fail() {
+ var msg = "{% trans 'Asset Deleting failed.' %}";
+ swal("{% trans 'Asset Delete' %}", msg, "error");
+ }
function success(data) {
url = setUrlParam(the_url, 'spm', data.spm);
requestApi({
@@ -268,13 +272,10 @@ $(document).ready(function(){
swal("{% trans 'Asset Delete' %}", msg, "success");
reloadTable();
},
+ error: fail,
flash_message: false,
});
}
- function fail() {
- var msg = "{% trans 'Asset Deleting failed.' %}";
- swal("{% trans 'Asset Delete' %}", msg, "error");
- }
requestApi({
url: "{% url 'api-common:resources-cache' %}",
method: 'POST',
diff --git a/apps/assets/templates/assets/domain_detail.html b/apps/assets/templates/assets/domain_detail.html
index 5b01c30fe..119b58080 100644
--- a/apps/assets/templates/assets/domain_detail.html
+++ b/apps/assets/templates/assets/domain_detail.html
@@ -63,10 +63,6 @@
{% trans 'Date created' %}: |
{{ object.date_created }} |
-
- {% trans 'Created by' %}: |
- {{ object.created_by }} |
-
{% trans 'Comment' %}: |
{{ object.comment }} |
diff --git a/apps/assets/templates/assets/system_user_detail.html b/apps/assets/templates/assets/system_user_detail.html
index b26cfbf11..01e71fc1c 100644
--- a/apps/assets/templates/assets/system_user_detail.html
+++ b/apps/assets/templates/assets/system_user_detail.html
@@ -106,7 +106,7 @@
{% trans 'Created by' %}: |
- {{ asset_group.created_by }} |
+ {{ system_user.created_by }} |
{% trans 'Comment' %}: |
diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo
index f9e23c281..b952d9ab4 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 7356b96e3..27dc9addd 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-03-12 17:27+0800\n"
+"POT-Creation-Date: 2020-03-17 13:50+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ibuler \n"
"Language-Team: JumpServer team\n"
@@ -535,7 +535,7 @@ msgstr "详情"
#: xpack/plugins/cloud/templates/cloud/account_detail.html:20
#: xpack/plugins/cloud/templates/cloud/account_list.html:40
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:26
-#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:57
+#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:60
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:46
#: xpack/plugins/orgs/templates/orgs/org_detail.html:20
#: xpack/plugins/orgs/templates/orgs/org_list.html:93
@@ -587,7 +587,7 @@ msgstr "更新"
#: xpack/plugins/cloud/templates/cloud/account_detail.html:24
#: xpack/plugins/cloud/templates/cloud/account_list.html:42
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:30
-#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:58
+#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:61
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:47
#: xpack/plugins/orgs/templates/orgs/org_detail.html:24
#: xpack/plugins/orgs/templates/orgs/org_list.html:95
@@ -727,6 +727,14 @@ msgstr "不能修改根节点名称"
msgid "Deletion failed and the node contains children or assets"
msgstr "删除失败,节点包含子节点或资产"
+#: assets/backends/db.py:244
+msgid "Could not remove asset admin user"
+msgstr "不能移除资产的管理用户账号"
+
+#: assets/backends/db.py:305
+msgid "Latest version could not be delete"
+msgstr "最新版本的不能被删除"
+
#: assets/forms/asset.py:83 assets/models/asset.py:196
#: assets/models/user.py:109 assets/templates/assets/asset_detail.html:186
#: assets/templates/assets/asset_detail.html:194
@@ -3169,23 +3177,23 @@ msgstr "{} 任务结束"
msgid "Result"
msgstr "结果"
-#: ops/models/command.py:59
+#: ops/models/command.py:64
msgid "Task start"
msgstr "任务开始"
-#: ops/models/command.py:81
+#: ops/models/command.py:86
msgid "Command `{}` is forbidden ........"
msgstr "命令 `{}` 不允许被执行 ......."
-#: ops/models/command.py:88
+#: ops/models/command.py:93
msgid "Task end"
msgstr "任务结束"
-#: ops/tasks.py:63
+#: ops/tasks.py:65
msgid "Clean task history period"
msgstr "定期清除任务历史"
-#: ops/tasks.py:76
+#: ops/tasks.py:78
msgid "Clean celery log period"
msgstr "定期清除Celery日志"
@@ -3349,6 +3357,7 @@ msgstr "结束"
#: ops/templates/ops/task_adhoc.html:17 ops/templates/ops/task_detail.html:18
#: ops/templates/ops/task_history.html:17 ops/views/adhoc.py:50
+#: ops/views/adhoc.py:92
msgid "Task detail"
msgstr "任务详情"
@@ -3383,7 +3392,7 @@ msgstr "内容"
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:135
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:54
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:138
-#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:55
+#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:58
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:44
msgid "Run"
msgstr "执行"
@@ -4261,7 +4270,9 @@ msgid "Please enter Password: {}"
msgstr "请输入密码: {}"
#: settings/utils/ldap.py:420
-msgid "Please enter correct Bind DN and Password: {}"
+#, fuzzy
+#| msgid "Please enter correct Bind DN and Password: {}"
+msgid "Please enter Correct Bind DN and Password: {}"
msgstr "请输入正确的绑定DN和密码: {}"
#: settings/utils/ldap.py:438
@@ -4970,7 +4981,6 @@ msgid "Session detail"
msgstr "会话详情"
#: terminal/templates/terminal/session_commands.html:29
-#: terminal/templates/terminal/session_detail.html:29
#: terminal/views/command.py:22
msgid "Command list"
msgstr "命令记录列表"
@@ -6575,7 +6585,7 @@ msgid "Run task manually"
msgstr "手动执行任务"
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:178
-#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:99
+#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:102
msgid "Sync success"
msgstr "同步成功"
diff --git a/apps/ops/inventory.py b/apps/ops/inventory.py
index 59179b5c7..b0fe5f8ef 100644
--- a/apps/ops/inventory.py
+++ b/apps/ops/inventory.py
@@ -92,7 +92,7 @@ class JMSInventory(JMSBaseInventory):
for asset in assets:
host = self.convert_to_ansible(asset, run_as_admin=run_as_admin)
- if run_as:
+ if run_as is not None:
run_user_info = self.get_run_user_info(host)
host.update(run_user_info)
if become_info and asset.is_unixlike():
@@ -104,7 +104,7 @@ class JMSInventory(JMSBaseInventory):
def get_run_user_info(self, host):
from assets.backends import AssetUserManager
- if not self.run_as:
+ if self.run_as is None:
return {}
try:
diff --git a/apps/ops/models/adhoc.py b/apps/ops/models/adhoc.py
index 01d1e1adb..faa3ac01f 100644
--- a/apps/ops/models/adhoc.py
+++ b/apps/ops/models/adhoc.py
@@ -206,7 +206,7 @@ class AdHoc(OrgModelMixin):
def __str__(self):
return "{} of {}".format(self.task.name, self.short_id)
- def __eq__(self, other):
+ def same_with(self, other):
if not isinstance(other, self.__class__):
return False
fields_check = []
diff --git a/apps/ops/models/command.py b/apps/ops/models/command.py
index 53aeff2b9..662131bc5 100644
--- a/apps/ops/models/command.py
+++ b/apps/ops/models/command.py
@@ -33,7 +33,12 @@ class CommandExecution(OrgModelMixin):
@property
def inventory(self):
- return JMSInventory(self.hosts.all(), run_as=self.run_as.username)
+ if self.run_as.username_same_with_user:
+ username = self.user.username
+ else:
+ username = self.run_as.username
+ inv = JMSInventory(self.hosts.all(), run_as=username)
+ return inv
@property
def result(self):
diff --git a/apps/ops/tasks.py b/apps/ops/tasks.py
index 33d7cb850..0967ac482 100644
--- a/apps/ops/tasks.py
+++ b/apps/ops/tasks.py
@@ -10,6 +10,7 @@ from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from common.utils import get_logger, get_object_or_none, get_disk_usage
+from orgs.utils import tmp_to_root_org
from .celery.decorator import (
register_as_period_task, after_app_shutdown_clean_periodic,
after_app_ready_start
@@ -44,7 +45,8 @@ def run_ansible_task(tid, callback=None, **kwargs):
@shared_task(soft_time_limit=60, queue="ansible")
def run_command_execution(cid, **kwargs):
- execution = get_object_or_none(CommandExecution, id=cid)
+ with tmp_to_root_org():
+ execution = get_object_or_none(CommandExecution, id=cid)
if execution:
try:
os.environ.update({
diff --git a/apps/ops/urls/view_urls.py b/apps/ops/urls/view_urls.py
index 592ae9d93..f17fb8662 100644
--- a/apps/ops/urls/view_urls.py
+++ b/apps/ops/urls/view_urls.py
@@ -15,7 +15,7 @@ urlpatterns = [
path('task//adhoc/', views.TaskAdhocView.as_view(), name='task-adhoc'),
path('task//executions/', views.TaskExecutionView.as_view(), name='task-execution'),
path('adhoc//', views.AdHocDetailView.as_view(), name='adhoc-detail'),
- path('adhoc//executions/', views.AdHocExecutionView.as_view(), name='adhoc-history'),
+ path('adhoc//executions/', views.AdHocExecutionView.as_view(), name='adhoc-execution'),
path('adhoc/executions//', views.AdHocExecutionDetailView.as_view(), name='adhoc-execution-detail'),
path('celery/task//log/', views.CeleryTaskLogView.as_view(), name='celery-task-log'),
diff --git a/apps/ops/utils.py b/apps/ops/utils.py
index 16ba8e648..81b5a1afd 100644
--- a/apps/ops/utils.py
+++ b/apps/ops/utils.py
@@ -56,7 +56,7 @@ def update_or_create_ansible_task(
new_hosts = set([str(asset.id) for asset in hosts])
hosts_same = old_hosts == new_hosts
- if not adhoc or adhoc != new_adhoc or not hosts_same:
+ if not adhoc or not adhoc.same_with(new_adhoc) or not hosts_same:
logger.debug(_("Update task content: {}").format(task_name))
new_adhoc.save()
new_adhoc.hosts.set(hosts)
diff --git a/apps/ops/views/adhoc.py b/apps/ops/views/adhoc.py
index b8d90f092..e21c7b575 100644
--- a/apps/ops/views/adhoc.py
+++ b/apps/ops/views/adhoc.py
@@ -89,7 +89,7 @@ class AdHocDetailView(PermissionsMixin, DetailView):
def get_context_data(self, **kwargs):
context = {
'app': _('Ops'),
- 'action': 'Task version detail',
+ 'action': _('Task detail'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
diff --git a/apps/perms/signals_handler.py b/apps/perms/signals_handler.py
index 1be6ce9f4..7a40bcb66 100644
--- a/apps/perms/signals_handler.py
+++ b/apps/perms/signals_handler.py
@@ -62,6 +62,34 @@ def on_asset_permission_system_users_changed(sender, instance=None, action='',
system_user.users.add(*tuple(users))
+@receiver(m2m_changed, sender=AssetPermission.users.through)
+def on_asset_permission_users_changed(sender, instance=None, action='',
+ reverse=False, **kwargs):
+ if action != 'post_add' and reverse:
+ return
+ logger.debug("Asset permission users change signal received")
+ users = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
+ system_users = instance.system_users.all()
+
+ for system_user in system_users:
+ if system_user.username_same_with_user:
+ system_user.users.add(*tuple(users))
+
+
+@receiver(m2m_changed, sender=AssetPermission.user_groups.through)
+def on_asset_permission_user_groups_changed(sender, instance=None, action='',
+ reverse=False, **kwargs):
+ if action != 'post_add' and reverse:
+ return
+ logger.debug("Asset permission user groups change signal received")
+ groups = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
+ system_users = instance.system_users.all()
+
+ for system_user in system_users:
+ if system_user.username_same_with_user:
+ system_user.groups.add(*tuple(groups))
+
+
@receiver(m2m_changed, sender=RemoteAppPermission.system_users.through)
def on_remote_app_permission_system_users_changed(sender, instance=None,
action='', reverse=False, **kwargs):
@@ -77,3 +105,17 @@ def on_remote_app_permission_system_users_changed(sender, instance=None,
if system_user.username_same_with_user:
system_user.groups.add(*tuple(groups))
system_user.users.add(*tuple(users))
+
+
+@receiver(m2m_changed, sender=RemoteAppPermission.users.through)
+def on_remoteapps_permission_users_changed(sender, instance=None, action='',
+ reverse=False, **kwargs):
+ on_asset_permission_users_changed(sender, instance=instance, action=action,
+ reverse=reverse, **kwargs)
+
+
+@receiver(m2m_changed, sender=RemoteAppPermission.user_groups.through)
+def on_remoteapps_permission_user_groups_changed(sender, instance=None, action='',
+ reverse=False, **kwargs):
+ on_asset_permission_user_groups_changed(sender, instance=instance,
+ action=action, reverse=reverse, **kwargs)
diff --git a/apps/static/img/login_image.png b/apps/static/img/login_image.png
index 11a19957e..60c851e78 100644
Binary files a/apps/static/img/login_image.png and b/apps/static/img/login_image.png differ
diff --git a/apps/terminal/forms/storage.py b/apps/terminal/forms/storage.py
index a94375e81..3b586560c 100644
--- a/apps/terminal/forms/storage.py
+++ b/apps/terminal/forms/storage.py
@@ -117,13 +117,6 @@ class ReplayStorageCephForm(BaseReplayStorageForm):
)
ceph_endpoint = forms.CharField(
max_length=128, label=_('Endpoint'), required=False,
- help_text=_(
- """
- S3: http://s3.{REGION_NAME}.amazonaws.com
- S3(China): http://s3.{REGION_NAME}.amazonaws.com.cn
- Example: http://s3.cn-north-1.amazonaws.com.cn
- """
- )
)
diff --git a/apps/terminal/templates/terminal/session_detail.html b/apps/terminal/templates/terminal/session_detail.html
index 26ec1c785..1863ad75f 100644
--- a/apps/terminal/templates/terminal/session_detail.html
+++ b/apps/terminal/templates/terminal/session_detail.html
@@ -26,7 +26,7 @@
-
{% trans 'Command list' %}
+
{{ object.id }}